home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / c-runtime / patches / objc-actions.c next >
Encoding:
C/C++ Source or Header  |  1992-08-18  |  139.8 KB  |  5,187 lines

  1. /* Implement classes and message passing for Objective C.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.    Author: Steve Naroff.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22.  *      Purpose: This module implements the Objective-C 4.0 language.
  23.  *
  24.  *      compatibility issues (with the Stepstone translator):
  25.  *
  26.  *    - does not recognize the following 3.3 constructs.
  27.  *      @requires, @classes, @messages, = (...)
  28.  *    - methods with variable arguments must conform to ANSI standard.
  29.  *    - tagged structure definitions that appear in BOTH the interface
  30.  *      and implementation are not allowed.
  31.  *      - public/private: all instance variables are public within the
  32.  *        context of the implementation...I consider this to be a bug in
  33.  *        the translator.
  34.  *      - statically allocated objects are not supported. the user will
  35.  *        receive an error if this service is requested.
  36.  *
  37.  *      code generation `options':
  38.  *
  39.  *      - OBJC_INT_SELECTORS, OBJC_SELECTORS_WITHOUT_LABELS, NEXT_OBJC_RUNTIME
  40.  */
  41.  
  42. #include <stdio.h>
  43. #include "config.h"
  44. #include "tree.h"
  45. #include "c-tree.h"
  46. #include "c-lex.h"
  47. #include "flags.h"
  48. #include "objc-actions.h"
  49. #include "input.h"
  50.  
  51. /* Define the special tree codes that we use.  */
  52.  
  53. /* Table indexed by tree code giving a string containing a character
  54.    classifying the tree code.  Possibilities are
  55.    t, d, s, c, r, <, 1 and 2.  See objc-tree.def for details.  */
  56.  
  57. #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
  58.  
  59. char *objc_tree_code_type[] = {
  60.   "x",
  61. #include "objc-tree.def"
  62. };
  63. #undef DEFTREECODE
  64.  
  65. /* Table indexed by tree code giving number of expression
  66.    operands beyond the fixed part of the node structure.
  67.    Not used for types or decls.  */
  68.  
  69. #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
  70.  
  71. int objc_tree_code_length[] = {
  72.   0,
  73. #include "objc-tree.def"
  74. };
  75. #undef DEFTREECODE
  76.  
  77. /* Names of tree components.
  78.    Used for printing out the tree and error messages.  */
  79. #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
  80.  
  81. char *objc_tree_code_name[] = {
  82.   "@@dummy",
  83. #include "objc-tree.def"
  84. };
  85. #undef DEFTREECODE
  86.  
  87. /* Set up for use of obstacks.  */
  88.  
  89. #include "obstack.h"
  90.  
  91. #define obstack_chunk_alloc xmalloc
  92. #define obstack_chunk_free free
  93.  
  94. /* This obstack is used to accumulate the encoding of a data type.  */
  95. static struct obstack util_obstack;
  96. /* This points to the beginning of obstack contents,
  97.    so we can free the whole contents.  */
  98. char *util_firstobj;
  99.  
  100. /* for encode_method_def */
  101. #include "rtl.h"
  102.  
  103. #define OBJC_VERSION    2
  104.  
  105. #define NULLT    (tree) 0
  106.  
  107. #define OBJC_ENCODE_INLINE_DEFS     0
  108. #define OBJC_ENCODE_DONT_INLINE_DEFS    1
  109.  
  110. /*** Private Interface (procedures) ***/
  111.  
  112. /* code generation */
  113.  
  114. static void synth_module_prologue ();
  115. static char *build_module_descriptor ();
  116. static tree init_module_descriptor ();
  117. static void build_module_entry ();
  118. static tree build_objc_method_call ();
  119. static void build_message_selector_pool ();
  120. static void build_selector_translation_table ();
  121. static tree build_ivar_chain ();
  122.  
  123. static tree build_ivar_template ();
  124. static tree build_method_template ();
  125. static tree build_private_template ();
  126. static void build_class_template ();
  127. static void build_category_template ();
  128. static tree build_super_template ();
  129.  
  130. static void synth_forward_declarations ();
  131. static void generate_ivar_lists ();
  132. static void generate_dispatch_tables ();
  133. static void generate_shared_structures ();
  134.  
  135. static tree build_msg_pool_reference ();
  136. static tree init_selector ();
  137. static tree build_keword_selector ();
  138. static tree synth_id_with_class_suffix ();
  139.  
  140. /* misc. bookkeeping */
  141.  
  142. typedef struct hashedEntry     *hash;
  143. typedef struct hashedAttribute  *attr;
  144.  
  145. struct hashedAttribute {
  146.         attr    next;
  147.         tree    value;
  148. };
  149. struct hashedEntry {
  150.         attr    list;
  151.     hash    next;
  152.     tree     key;
  153. };
  154. static void hash_init ();
  155. static void hash_enter ();
  156. static hash hash_lookup ();
  157. static void hash_add_attr ();
  158. static tree lookup_method ();
  159. static tree lookup_instance_method_static ();
  160. static tree lookup_class_method_static ();
  161. static tree add_class ();
  162. static int  add_selector_reference ();
  163. static void add_class_reference ();
  164. static int  add_objc_string ();
  165.  
  166. /* type encoding */
  167.  
  168. static void encode_aggregate ();
  169. static void encode_bitfield ();
  170. static void encode_type ();
  171. static void encode_field_decl ();
  172.  
  173. static void really_start_method ();
  174. static int  comp_method_with_proto ();
  175. static int  comp_proto_with_proto ();
  176. static tree get_arg_type_list ();
  177. static tree expr_last ();
  178.  
  179. /* utilities for debugging and error diagnostics: */
  180.  
  181. static void warn_with_method ();
  182. static void error_with_method ();
  183. static void error_with_ivar ();
  184. static char *gen_method_decl ();
  185. static char *gen_declaration ();
  186. static char *gen_declarator ();
  187. static int is_complex_decl ();
  188. static void adorn_decl ();
  189. static void dump_interfaces ();
  190.  
  191. /*** Private Interface (data) ***/
  192.  
  193. /* reserved tag definitions: */
  194.  
  195. #define TYPE_ID            "id"
  196. #define TAG_OBJECT        "objc_object"
  197. #define TAG_CLASS        "objc_class"
  198. #define TAG_SUPER        "objc_super"
  199. #define TAG_SELECTOR        "objc_selector"
  200.  
  201. #define _TAG_CLASS        "_objc_class"
  202. #define _TAG_IVAR        "_objc_ivar"
  203. #define _TAG_IVAR_LIST        "_objc_ivar_list"
  204. #define _TAG_METHOD        "_objc_method"
  205. #define _TAG_METHOD_LIST    "_objc_method_list"
  206. #define _TAG_CATEGORY        "_objc_category"
  207. #define _TAG_MODULE        "_objc_module"
  208. #define _TAG_SYMTAB        "_objc_symtab"
  209. #define _TAG_SUPER        "_objc_super"
  210.  
  211. /* set by `continue_class ()' and checked by `is_public ()' */
  212.  
  213. #define TREE_STATIC_TEMPLATE(record_type) (TREE_PUBLIC(record_type))
  214. #define TYPED_OBJECT(type) \
  215.        (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
  216.  
  217. /* some commonly used instances of "identifier_node". */
  218.  
  219. static tree self_id, _cmd_id;
  220.  
  221. static tree self_decl, _msg_decl, _msgSuper_decl;
  222. static tree objc_getClass_decl, objc_getMetaClass_decl;
  223.  
  224. static tree super_type, selector_type, id_type, class_type;
  225. static tree instance_type;
  226.  
  227. static tree interface_chain = NULLT;
  228.  
  229. /* chains to manage selectors that are referenced and defined in the module */
  230.  
  231. static tree cls_ref_chain = NULLT;    /* classes referenced */
  232. static tree sel_ref_chain = NULLT;    /* selectors referenced */
  233. static tree sel_refdef_chain = NULLT;    /* selectors references & defined */
  234. static int  max_selector_index;        /* total # of selector referenced */
  235.  
  236. /* hash tables to manage the global pool of method prototypes */
  237.  
  238. static hash *nst_method_hash_list = 0;
  239. static hash *cls_method_hash_list = 0;
  240.  
  241. /* the following are used when compiling a class implementation.
  242.  *
  243.  * implementation_template will normally be an anInterface, however if
  244.  * none exists this will be equal to implementation_context...it is
  245.  * set in start_class.
  246.  */
  247.  
  248. /* backend data declarations */
  249.  
  250. static tree _OBJC_SYMBOLS_decl;
  251. static tree     _OBJC_INSTANCE_VARIABLES_decl, _OBJC_CLASS_VARIABLES_decl;
  252. static tree     _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl;
  253. static tree     _OBJC_CLASS_decl, _OBJC_METACLASS_decl;
  254. #ifdef OBJC_SELECTORS_WITHOUT_LABELS
  255. static tree     _OBJC_SELECTOR_REFERENCES_decl;
  256. #endif
  257. static tree _OBJC_MODULES_decl;
  258. static tree _OBJC_STRINGS_decl;
  259.  
  260. static tree implementation_context = NULLT,
  261.         implementation_template = NULLT;
  262.  
  263. struct imp_entry {
  264.   struct imp_entry *next;
  265.   tree imp_context;
  266.   tree imp_template;
  267.   tree class_decl;        /* _OBJC_CLASS_<my_name>; */
  268.   tree meta_decl;        /* _OBJC_METACLASS_<my_name>; */
  269. };
  270. static struct imp_entry *imp_list = 0;
  271. static int imp_count = 0;    /* `@implementation' */
  272. static int cat_count = 0;    /* `@category' */
  273.  
  274. static tree objc_class_template, objc_category_template, _PRIVATE_record;
  275. static tree _clsSuper_ref, __clsSuper_ref;
  276.  
  277. static tree objc_method_template, objc_ivar_template;
  278. static tree objc_symtab_template, objc_module_template;
  279. static tree objc_super_template, objc_object_reference;
  280.  
  281. static tree objc_object_id, objc_class_id;
  282. static tree _OBJC_SUPER_decl;
  283.  
  284. static tree method_context = NULLT;
  285. static int  method_slot = 0;    /* used by start_method_def */
  286.  
  287. #define BUFSIZE        512
  288.  
  289. static char *errbuf;    /* a buffer for error diagnostics */
  290.  
  291. extern char *strcpy (), *strcat ();
  292.  
  293. extern tree groktypename_in_parm_context ();
  294.  
  295. extern struct obstack permanent_obstack, *current_obstack,  *rtl_obstack;
  296.  
  297. /* data imported from toplev.c  */
  298.  
  299. extern char *dump_base_name;
  300.  
  301. /* Open and close the file for outputting class declarations, if requested.  */
  302.  
  303. int flag_gen_declaration = 0;
  304.  
  305. FILE *gen_declaration_file;
  306.  
  307. /* Warn if multiple methods are seen for the same selector, but with
  308.    different argument types. */
  309.  
  310. int warn_selector = 0;
  311.  
  312. void
  313. lang_init ()
  314. {
  315.   /* the beginning of the file is a new line; check for # */
  316.   /* With luck, we discover the real source file's name from that
  317.      and put it in input_filename.  */
  318.   ungetc (check_newline (), finput);
  319.  
  320.   /* If gen_declaration desired, open the output file.  */
  321.   if (flag_gen_declaration)
  322.     {
  323.       int dump_base_name_length = strlen (dump_base_name);
  324.       register char *dumpname = (char *) xmalloc (dump_base_name_length + 7);
  325.       strcpy (dumpname, dump_base_name);
  326.       strcat (dumpname, ".decl");
  327.       gen_declaration_file = fopen (dumpname, "w");
  328.       if (gen_declaration_file == 0)
  329.     pfatal_with_name (dumpname);
  330.     }
  331.  
  332.   if (doing_objc_thang)
  333.     init_objc ();
  334. }
  335.  
  336. void
  337. objc_finish ()
  338. {
  339.   if (doing_objc_thang)
  340.     finish_objc ();        /* Objective-C finalization */
  341.  
  342.   if (gen_declaration_file)
  343.     fclose (gen_declaration_file);
  344. }
  345.  
  346. void
  347. lang_finish ()
  348. {
  349. }
  350.  
  351. int
  352. lang_decode_option (p)
  353.      char *p;
  354. {
  355.   if (!strcmp (p, "-lang-objc"))
  356.     doing_objc_thang = 1;
  357.   else if (!strcmp (p, "-gen-decls"))
  358.     flag_gen_declaration = 1;
  359.   else if (!strcmp (p, "-Wselector"))
  360.     warn_selector = 1;
  361.   else if (!strcmp (p, "-Wno-selector"))
  362.     warn_selector = 0;
  363.   else
  364.     return c_decode_option (p);
  365.  
  366.   return 1;
  367. }
  368.  
  369. static tree
  370. define_decl (declarator, declspecs)
  371.      tree declarator;
  372.      tree declspecs;
  373. {
  374.   tree decl = start_decl (declarator, declspecs, 0);
  375.   finish_decl (decl, NULLT, NULLT);
  376.   return decl;
  377. }
  378.  
  379. /*
  380.  * rules for statically typed objects...called from `c-typeck.comptypes'.
  381.  *
  382.  * an assignment of the form `a' = `b' is permitted if:
  383.  *
  384.  *   - `a' is of type "id".
  385.  *   - `a' and `b' are the same class type.
  386.  *   - `a' and `b' are of class types A and B such that B is a descendant
  387.  *     of A.
  388.  */
  389.  
  390. int
  391. maybe_objc_comptypes (lhs, rhs)
  392.      tree lhs, rhs;
  393. {
  394.   if (doing_objc_thang)
  395.     return objc_comptypes (lhs, rhs);
  396.   return 0;
  397. }
  398.  
  399. int
  400. objc_comptypes (lhs, rhs)
  401.      tree lhs;
  402.      tree rhs;
  403. {
  404.   /* `id' = `<class> *', `<class> *' = `id' */
  405.  
  406.   if ((TYPE_NAME (lhs) == objc_object_id && TYPED_OBJECT (rhs))
  407.       || (TYPED_OBJECT (lhs) && TYPE_NAME (rhs) == objc_object_id))
  408.     return 1;
  409.  
  410.   /* `id' = `Class', `Class' = `id' */
  411.  
  412.  
  413.   else if ((TYPE_NAME (lhs) == objc_object_id &&
  414.         TYPE_NAME (rhs) == objc_class_id) ||
  415.        (TYPE_NAME (lhs) == objc_class_id &&
  416.         TYPE_NAME (rhs) == objc_object_id))
  417.     return 1;
  418.  
  419.   /* `<class> *' = `<class> *' */
  420.  
  421.   else if (TYPED_OBJECT (lhs) && TYPED_OBJECT (rhs))
  422.     {
  423.       tree lname = TYPE_NAME (lhs), rname = TYPE_NAME (rhs);
  424.  
  425.       if (lname == rname)
  426.     return 1;
  427.       else
  428.     {
  429.       /* if the left hand side is a super class of the right hand side,
  430.          allow it...
  431.          */
  432.       tree rinter = lookup_interface (rname);
  433.  
  434.       while (rinter)
  435.         {
  436.           if (lname == CLASS_SUPER_NAME (rinter))
  437.         return 1;
  438.  
  439.           rinter = lookup_interface (CLASS_SUPER_NAME (rinter));
  440.         }
  441.  
  442.       return 0;
  443.     }
  444.     }
  445.   else
  446.     return 0;
  447. }
  448.  
  449. /* Called from c-decl.c before all calls to rest_of_decl_compilation.  */
  450.  
  451. void
  452. maybe_objc_check_decl (decl)
  453.      tree decl;
  454. {
  455.   if (doing_objc_thang)
  456.     objc_check_decl (decl);
  457. }
  458.  
  459. void
  460. objc_check_decl (decl)
  461.      tree decl;
  462. {
  463.   tree type = TREE_TYPE (decl);
  464.   static int alreadyWarned = 0;
  465.  
  466.   if (TREE_CODE (type) == RECORD_TYPE && TREE_STATIC_TEMPLATE (type))
  467.     {
  468.       if (!alreadyWarned)
  469.     {
  470.       error ("GNU compiler does not support statically allocated objects");
  471.       alreadyWarned = 1;
  472.     }
  473.       error_with_decl (decl, "`%s' cannot be statically allocated");
  474.     }
  475. }
  476.  
  477. /* implement static typing. at this point, we know we have an interface... */
  478.  
  479. tree
  480. get_static_reference (interface)
  481.      tree interface;
  482. {
  483.   return xref_tag (RECORD_TYPE, CLASS_NAME (interface));
  484. }
  485.  
  486. /* Create and push a decl for a built-in external variable or field NAME.
  487.    CODE says which.
  488.    TYPE is its data type.  */
  489.  
  490. static tree
  491. create_builtin_decl (code, type, name)
  492.      enum tree_code code;
  493.      tree type;
  494.      char *name;
  495. {
  496.   tree decl = build_decl (code, get_identifier (name), type);
  497.   if (code == VAR_DECL)
  498.     {
  499.       DECL_EXTERNAL (decl) = 1;
  500.       TREE_PUBLIC (decl) = 1;
  501.       make_decl_rtl (decl, 0, 1);
  502.       pushdecl (decl);
  503.     }
  504.   return decl;
  505. }
  506.  
  507. /*
  508.  *    purpose: "play" parser, creating/installing representations
  509.  *         of the declarations that are required by Objective-C.
  510.  *
  511.  *    model:
  512.  *
  513.  *        type_spec--------->sc_spec
  514.  *        (tree_list)        (tree_list)
  515.  *            |                  |
  516.  *            |                  |
  517.  *        identifier_node    identifier_node
  518.  */
  519. static void
  520. synth_module_prologue ()
  521. {
  522.   tree expr_decl, temp_type;
  523.  
  524.   /* defined in `objc.h' */
  525.   objc_object_id = get_identifier (TAG_OBJECT);
  526.  
  527.   objc_object_reference = xref_tag (RECORD_TYPE, objc_object_id);
  528.  
  529.   id_type = build_pointer_type (objc_object_reference);
  530.  
  531.   objc_class_id = get_identifier (TAG_CLASS);
  532.   
  533.   class_type = build_pointer_type (xref_tag (RECORD_TYPE, objc_class_id));
  534.  
  535.   /* Declare type of selector-objects that represent an operation name.  */
  536.  
  537. #ifdef OBJC_INT_SELECTORS
  538.   /* `unsigned int' */
  539.   selector_type = unsigned_type_node;
  540. #else
  541.   /* `struct objc_selector *' */
  542.   selector_type
  543.     = build_pointer_type (xref_tag (RECORD_TYPE,
  544.                     get_identifier (TAG_SELECTOR)));
  545. #endif /* not OBJC_INT_SELECTORS */
  546.  
  547.   /* struct objc_object *objc_msgSend (id, SEL, ...); */
  548.  
  549.   temp_type
  550.     = build_function_type (id_type,
  551.                tree_cons (NULL_TREE, id_type,
  552.                       tree_cons (NULLT, selector_type, NULLT)));
  553.  
  554.   _msg_decl = builtin_function ("objc_msgSend", temp_type, NOT_BUILT_IN, 0);
  555.  
  556.   /* struct objc_object *objc_msgSendSuper (void *, SEL, ...); */
  557.  
  558.   temp_type
  559.     = build_function_type (id_type,
  560.                tree_cons (NULL_TREE, ptr_type_node,
  561.                       tree_cons (NULLT, selector_type, NULLT)));
  562.  
  563.   _msgSuper_decl = builtin_function ("objc_msgSendSuper",
  564.                      temp_type, NOT_BUILT_IN, 0);
  565.  
  566.   /* id objc_getClass (); */
  567.   
  568.   temp_type = build_function_type (id_type, NULLT);
  569.  
  570.   objc_getClass_decl
  571.     = builtin_function ("objc_getClass", temp_type, NOT_BUILT_IN, 0);
  572.  
  573.   /* id objc_getMetaClass (); */
  574.  
  575.   objc_getMetaClass_decl
  576.     = builtin_function ("objc_getMetaClass", temp_type, NOT_BUILT_IN, 0);
  577.  
  578.   /* extern SEL _OBJC_SELECTOR_REFERENCES[]; */
  579.  
  580. #ifdef OBJC_SELECTORS_WITHOUT_LABELS
  581.   _OBJC_SELECTOR_REFERENCES_decl
  582.     = create_builtin_decl (VAR_DECL, build_array_type (selector_type, NULLT),
  583.                "_OBJC_SELECTOR_REFERENCES");
  584. #endif
  585. }
  586.  
  587. /*
  588.  * custom "build_string ()" which sets TREE_TYPE!
  589.  */
  590. static tree
  591. my_build_string (len, str)
  592.      int len;
  593.      char *str;
  594. {
  595.   int wide_flag = 0;
  596.   tree aString = build_string (len, str);
  597.   /*
  598.    *  some code from "combine_strings ()", which is local to c-parse.y.
  599.    */
  600.   if (TREE_TYPE (aString) == int_array_type_node)
  601.     wide_flag = 1;
  602.  
  603.   TREE_TYPE (aString) =
  604.     build_array_type (wide_flag ? integer_type_node : char_type_node,
  605.               build_index_type (build_int_2 (len - 1, 0)));
  606.  
  607.   TREE_CONSTANT (aString) = 1;    /* puts string in the ".text" segment */
  608.   TREE_STATIC (aString) = 1;
  609.  
  610.   return aString;
  611. }
  612.  
  613. /* Take care of defining and initializing _OBJC_SYMBOLS.  */
  614.  
  615. /* Predefine the following data type:
  616.  
  617.     struct _objc_symtab {
  618.         long sel_ref_cnt;
  619.         SEL *refs;
  620.         short cls_def_cnt;
  621.         short cat_def_cnt;
  622.         void *defs[cls_def_cnt + cat_def_cnt];
  623.     }; */
  624.  
  625. static void
  626. build_objc_symtab_template ()
  627. {
  628.   tree field_decl, field_decl_chain, index;
  629.  
  630.   objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (_TAG_SYMTAB));
  631.  
  632.   /* long sel_ref_cnt; */
  633.  
  634.   field_decl = create_builtin_decl (FIELD_DECL,
  635.                     long_integer_type_node,
  636.                     "sel_ref_cnt");
  637.   field_decl_chain = field_decl;
  638.  
  639.   /* SEL *refs; */
  640.  
  641.   field_decl = create_builtin_decl (FIELD_DECL,
  642.                     build_pointer_type (selector_type),
  643.                     "refs");
  644.   chainon (field_decl_chain, field_decl);
  645.  
  646.   /* short cls_def_cnt; */
  647.  
  648.   field_decl = create_builtin_decl (FIELD_DECL,
  649.                     short_integer_type_node,
  650.                     "cls_def_cnt");
  651.   chainon (field_decl_chain, field_decl);
  652.  
  653.   /* short cat_def_cnt; */
  654.  
  655.   field_decl = create_builtin_decl (FIELD_DECL,
  656.                     short_integer_type_node,
  657.                     "cat_def_cnt");
  658.   chainon (field_decl_chain, field_decl);
  659.  
  660.   /* void *defs[cls_def_cnt + cat_def_cnt]; */
  661.  
  662.   index = build_index_type (build_int_2 (imp_count + cat_count - 1, 0));
  663.   field_decl = create_builtin_decl (FIELD_DECL,
  664.                     build_array_type (ptr_type_node, index),
  665.                     "defs");
  666.   chainon (field_decl_chain, field_decl);
  667.  
  668.   finish_struct (objc_symtab_template, field_decl_chain);
  669. }
  670.  
  671. /* Create the initial value for the `defs' field of _objc_symtab.
  672.    This is a CONSTRUCTOR.  */
  673.  
  674. static tree
  675. init_def_list ()
  676. {
  677.   tree expr, initlist = NULLT;
  678.   struct imp_entry *impent;
  679.  
  680.   if (imp_count)
  681.     for (impent = imp_list; impent; impent = impent->next)
  682.       {
  683.     if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
  684.       {
  685.         expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
  686.         initlist = tree_cons (NULLT, expr, initlist);
  687.       }
  688.       }
  689.  
  690.   if (cat_count)
  691.     for (impent = imp_list; impent; impent = impent->next)
  692.       {
  693.     if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
  694.       {
  695.         expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0);
  696.         initlist = tree_cons (NULLT, expr, initlist);
  697.       }
  698.       }
  699.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  700. }
  701.  
  702. /* Construct the initial value for all of _objc_symtab.  */
  703.  
  704. static tree
  705. init_objc_symtab ()
  706. {
  707.   tree initlist;
  708.  
  709.   /* sel_ref_cnt = { ..., 5, ... } */
  710.  
  711.   if (sel_ref_chain)
  712.     initlist = build_tree_list (NULLT, build_int_2 (max_selector_index, 0));
  713.   else
  714.     initlist = build_tree_list (NULLT, build_int_2 (0, 0));
  715.  
  716.   /* refs = { ..., _OBJC_SELECTOR_REFERENCES, ... } */
  717.  
  718. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  719.   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  720. #else
  721.   if (sel_ref_chain)
  722.     initlist = tree_cons (NULLT, _OBJC_SELECTOR_REFERENCES_decl, initlist);
  723.   else
  724.     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  725. #endif
  726.  
  727.   /* cls_def_cnt = { ..., 5, ... } */
  728.  
  729.   initlist = tree_cons (NULLT, build_int_2 (imp_count, 0), initlist);
  730.  
  731.   /* cat_def_cnt = { ..., 5, ... } */
  732.  
  733.   initlist = tree_cons (NULLT, build_int_2 (cat_count, 0), initlist);
  734.  
  735.   /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */
  736.  
  737.   if (imp_count || cat_count)
  738.     initlist = tree_cons (NULLT, init_def_list (), initlist);
  739.  
  740.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  741. }
  742.  
  743. /* Push forward-declarations of all the categories
  744.    so that init_def_list can use them in a CONSTRUCTOR.  */
  745.  
  746. static void
  747. forward_declare_categories ()
  748. {
  749.   struct imp_entry *impent;
  750.   tree sav = implementation_context;
  751.   for (impent = imp_list; impent; impent = impent->next)
  752.     {
  753.       if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
  754.     {
  755.       /* Set an invisible arg to synth_id_with_class_suffix.  */
  756.       implementation_context = impent->imp_context;
  757.       impent->class_decl
  758.         = create_builtin_decl (VAR_DECL, objc_category_template,
  759.                    IDENTIFIER_POINTER (synth_id_with_class_suffix ("_OBJC_CATEGORY")));
  760.     }
  761.     }
  762.   implementation_context = sav;
  763. }
  764.  
  765. /* Create the declaration of _OBJC_SYMBOLS, with type `strict _objc_symtab'
  766.    and initialized appropriately.  */
  767.  
  768. static void
  769. generate_objc_symtab_decl ()
  770. {
  771.   tree sc_spec;
  772.  
  773.   if (!objc_category_template)
  774.     build_category_template ();
  775.  
  776.   /* forward declare categories */
  777.   if (cat_count)
  778.     forward_declare_categories ();
  779.  
  780.   if (!objc_symtab_template)
  781.     build_objc_symtab_template ();
  782.  
  783.   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
  784.  
  785.   _OBJC_SYMBOLS_decl = start_decl (get_identifier ("_OBJC_SYMBOLS"),
  786.                    tree_cons (NULLT, objc_symtab_template, sc_spec), 1);
  787.  
  788.   finish_decl (_OBJC_SYMBOLS_decl, init_objc_symtab (), NULLT);
  789. }
  790.  
  791. /*
  792.  *    tree_node------->tree_node----->...
  793.  *          |                |
  794.  *          | (value)        | (value)
  795.  *          |                |
  796.  *      expr             expr
  797.  */
  798. static tree
  799. init_module_descriptor ()
  800. {
  801.   tree initlist, expr;
  802.  
  803.   /* version = { 1, ... } */
  804.  
  805.   expr = build_int_2 (OBJC_VERSION, 0);
  806.   initlist = build_tree_list (NULLT, expr);
  807.  
  808.   /* size = { ..., sizeof (struct objc_module), ... } */
  809.  
  810.   expr = build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_module_template)) /
  811.               BITS_PER_UNIT, 0);
  812.   initlist = tree_cons (NULLT, expr, initlist);
  813.  
  814.   /* name = { ..., "foo.m", ... } */
  815.  
  816.   expr = build_msg_pool_reference (
  817.                    add_objc_string (get_identifier (input_filename)));
  818.   initlist = tree_cons (NULLT, expr, initlist);
  819.  
  820.   /* symtab = { ..., _OBJC_SYMBOLS, ... } */
  821.  
  822.   if (_OBJC_SYMBOLS_decl)
  823.     expr = build_unary_op (ADDR_EXPR, _OBJC_SYMBOLS_decl, 0);
  824.   else
  825.     expr = build_int_2 (0, 0);
  826.   initlist = tree_cons (NULLT, expr, initlist);
  827.  
  828.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  829. }
  830.  
  831. /* Write out the data structures to describe Objective C classes defined.
  832.    If appropriate, compile and output a setup function to initialize them.
  833.    Return a string which is the name of a function to call to initialize
  834.    the Objective C data structures for this file (and perhaps for other files
  835.    also).  */
  836.  
  837. static char *
  838. build_module_descriptor ()
  839. {
  840.   tree decl_specs, field_decl, field_decl_chain;
  841.  
  842.   objc_module_template = start_struct (RECORD_TYPE, get_identifier (_TAG_MODULE));
  843.  
  844.   /* long version; */
  845.  
  846.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
  847.   field_decl = get_identifier ("version");
  848.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  849.   field_decl_chain = field_decl;
  850.  
  851.   /* long  size; */
  852.  
  853.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
  854.   field_decl = get_identifier ("size");
  855.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  856.   chainon (field_decl_chain, field_decl);
  857.  
  858.   /* char  *name; */
  859.  
  860.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
  861.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
  862.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  863.   chainon (field_decl_chain, field_decl);
  864.  
  865.   /* struct objc_symtab *symtab; */
  866.  
  867.   decl_specs = get_identifier (_TAG_SYMTAB);
  868.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
  869.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("symtab"));
  870.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  871.   chainon (field_decl_chain, field_decl);
  872.  
  873.   finish_struct (objc_module_template, field_decl_chain);
  874.  
  875.   /* create an instance of "objc_module" */
  876.  
  877.   decl_specs = tree_cons (NULLT, objc_module_template,
  878.               build_tree_list (NULLT, ridpointers[(int) RID_STATIC]));
  879.  
  880.   _OBJC_MODULES_decl = start_decl (get_identifier ("_OBJC_MODULES"),
  881.                    decl_specs, 1);
  882.  
  883.   finish_decl (_OBJC_MODULES_decl, init_module_descriptor (), NULLT);
  884.  
  885.   /* Mark the decl to avoid "defined but not used" warning. */
  886.   DECL_IN_SYSTEM_HEADER (_OBJC_MODULES_decl) = 1;
  887.  
  888.   /* Generate a constructor call for the module descriptor. 
  889.      This code was generated by reading the grammar rules
  890.      of c-parse.y;  Therefore, it may not be the most efficient
  891.      way of generating the requisite code. */
  892. #ifndef NEXT_OBJC_RUNTIME
  893.   {
  894.     tree parms, function_decl, decelerator, void_list_node;
  895.     tree function_type;
  896.     char *buf;
  897.     char *global_object_name = 0;
  898.     tree t;
  899.  
  900.     /* Use a global object (which is already required to be unique over
  901.        the program) rather than the file name (which imposes extra
  902.        constraints).  -- Raeburn@MIT.EDU, 10 Jan 1990.  */
  903.  
  904.     /* Find the name of some global object defined in this file.  */
  905.     /* This doesn't work.  Lets choose something else.
  906.        dennis_glatting@trirex.com, 17aug92. */
  907.  
  908. /*    for (t = getdecls (); t; t = TREE_CHAIN (t))
  909.       if (TREE_PUBLIC (t) && !DECL_EXTERNAL (t) && DECL_INITIAL (t) != 0)
  910.     {
  911.       global_object_name = IDENTIFIER_POINTER (DECL_NAME (t));
  912.       break;
  913.     } */
  914.  
  915.     /* If none, use the name of the file.  */
  916.     if (!global_object_name)
  917.       {
  918.     char *p, *q;
  919.     global_object_name
  920.       = (char *) alloca (strlen (main_input_filename) + 1);
  921.  
  922.     p = main_input_filename;
  923.     q = global_object_name;
  924.  
  925.     /* Replace any weird characters in the file name.  */
  926.     for (; *p; p++)
  927.       if (! ((*p >= '0' && *p <= '9')
  928.          || (*p >= 'A' && *p <= 'Z')
  929.          || (*p >= 'a' && *p <= 'z')))
  930.         *q++ = '_';
  931.       else
  932.         *q++ = *p;
  933.     *q = 0;
  934.       }
  935.  
  936.     /* Make the constructor name from the name we have found.  */
  937.     buf = (char *) xmalloc (sizeof (CONSTRUCTOR_NAME_FORMAT)
  938.                 + strlen (global_object_name));
  939.     sprintf (buf, CONSTRUCTOR_NAME_FORMAT, global_object_name);
  940.  
  941.     /* Declare void __objc_execClass (void*); */
  942.  
  943.     void_list_node = build_tree_list (NULL_TREE, void_type_node);
  944.     function_type
  945.       = build_function_type (void_type_node,  
  946.                  tree_cons (NULL_TREE, ptr_type_node,  
  947.                     void_list_node));
  948.     function_decl = build_decl (FUNCTION_DECL,  
  949.                 get_identifier ("__objc_execClass"),  
  950.                 function_type);
  951.     DECL_EXTERNAL (function_decl) = 1;
  952.     TREE_PUBLIC (function_decl) = 1;
  953.     pushdecl (function_decl);
  954.     rest_of_decl_compilation (function_decl, 0, 0, 0);
  955.  
  956.     parms
  957.       = build_tree_list (NULLT,
  958.              build_unary_op (ADDR_EXPR, _OBJC_MODULES_decl, 0));
  959.     decelerator = build_function_call (function_decl, parms);
  960.  
  961.     /* void __objc_file_init () {objc_execClass(&L_OBJC_MODULES);}  */
  962.  
  963.     start_function (void_list_node,
  964.             build_parse_node (CALL_EXPR, get_identifier (buf),
  965.                       /* This has the format of the output
  966.                      of get_parm_info.  */
  967.                       tree_cons (NULL_TREE, NULL_TREE,
  968.                          void_list_node),
  969.                       NULL_TREE),
  970.             0, 0);
  971. #if 0 /* This should be turned back on later
  972.      for the systems where collect is not needed.  */
  973.     /* Make these functions nonglobal
  974.        so each file can use the same name.  */
  975.     TREE_PUBLIC (current_function_decl) = 0;
  976. #endif
  977.     TREE_USED (current_function_decl) = 1;
  978.     store_parm_decls ();
  979.  
  980.     assemble_external (function_decl);
  981.     c_expand_expr_stmt (decelerator);
  982.  
  983.     finish_function (0);
  984.  
  985.     /* Return the name of the constructor function.  */
  986.     return buf;
  987.   }
  988. #else /* NEXT_OBJC_RUNTIME */
  989.   return 0;
  990. #endif /* NEXT_OBJC_RUNTIME */
  991. }
  992.  
  993. /* extern const char _OBJC_STRINGS[]; */
  994.  
  995. static void
  996. generate_forward_declaration_to_string_table ()
  997. {
  998.   tree sc_spec, decl_specs, expr_decl;
  999.  
  1000.   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_EXTERN], NULLT);
  1001.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
  1002.  
  1003.   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
  1004.  
  1005.   _OBJC_STRINGS_decl = define_decl (expr_decl, decl_specs);
  1006. }
  1007.  
  1008. /* static char _OBJC_STRINGS[] = "..."; */
  1009.  
  1010. static void
  1011. build_message_selector_pool ()
  1012. {
  1013.   tree sc_spec, decl_specs, expr_decl;
  1014.   tree chain, string_expr;
  1015.   int goolengthtmp = 0, msg_pool_size = 0;
  1016.   char *string_goo;
  1017.  
  1018.   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
  1019.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], sc_spec);
  1020.  
  1021.   expr_decl = build_nt (ARRAY_REF, get_identifier ("_OBJC_STRINGS"), NULLT);
  1022.  
  1023.   _OBJC_STRINGS_decl = start_decl (expr_decl, decl_specs, 1);
  1024.  
  1025.   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
  1026.     msg_pool_size += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
  1027.  
  1028.   msg_pool_size++;
  1029.  
  1030.   string_goo = (char *)xmalloc (msg_pool_size);
  1031.   bzero (string_goo, msg_pool_size);
  1032.  
  1033.   for (chain = sel_refdef_chain; chain; chain = TREE_CHAIN (chain))
  1034.     {
  1035.       strcpy (string_goo + goolengthtmp, IDENTIFIER_POINTER (TREE_VALUE (chain)));
  1036.       goolengthtmp += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
  1037.     }
  1038.  
  1039.   string_expr = my_build_string (msg_pool_size, string_goo);
  1040.  
  1041.   finish_decl (_OBJC_STRINGS_decl, string_expr, NULLT);
  1042. }
  1043.  
  1044. /*
  1045.  * synthesize the following expr: (char *)&_OBJC_STRINGS[<offset>]
  1046.  *
  1047.  * the cast stops the compiler from issuing the following message:
  1048.  *
  1049.  * grok.m: warning: initialization of non-const * pointer from const *
  1050.  * grok.m: warning: initialization between incompatible pointer types
  1051.  */
  1052. static tree
  1053. build_msg_pool_reference (offset)
  1054.      int offset;
  1055. {
  1056.   tree expr = build_int_2 (offset, 0);
  1057.   tree cast;
  1058.  
  1059.   expr = build_array_ref (_OBJC_STRINGS_decl, expr);
  1060.   expr = build_unary_op (ADDR_EXPR, expr, 0);
  1061.  
  1062.   cast = build_tree_list (build_tree_list (NULLT, ridpointers[(int) RID_CHAR]),
  1063.               build1 (INDIRECT_REF, NULLT, NULLT));
  1064.   TREE_TYPE (expr) = groktypename (cast);
  1065.   return expr;
  1066. }
  1067.  
  1068. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1069. static tree
  1070. build_selector_reference (idx)
  1071.       int idx;
  1072. {
  1073.   tree ref, decl, name, ident;
  1074.   char buf[256];
  1075.   struct obstack *save_current_obstack = current_obstack;
  1076.   struct obstack *save_rtl_obstack = rtl_obstack;
  1077.  
  1078.   sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
  1079.  
  1080.   /* new stuff */
  1081.   rtl_obstack = current_obstack = &permanent_obstack;
  1082.   ident = get_identifier (buf);
  1083.  
  1084.   if (IDENTIFIER_GLOBAL_VALUE (ident))
  1085.     decl = IDENTIFIER_GLOBAL_VALUE (ident); /* set by pushdecl() */
  1086.   else 
  1087.     {
  1088.       decl = build_decl (VAR_DECL, ident, selector_type);
  1089.       DECL_EXTERNAL (decl) = 1;
  1090.       TREE_PUBLIC (decl) = 1;
  1091.       TREE_USED (decl) = 1;
  1092.   
  1093.       make_decl_rtl (decl, 0, 1); /* usually called from `rest_of_decl_compilation' */
  1094.       pushdecl_top_level (decl);  /* our `extended/custom' pushdecl in c-decl.c */
  1095.     }
  1096.   current_obstack = save_current_obstack;
  1097.   rtl_obstack = save_rtl_obstack;
  1098.  
  1099.   return decl;
  1100. }
  1101. #endif
  1102.  
  1103. static tree
  1104. init_selector (offset)
  1105.      int offset;
  1106. {
  1107.   tree expr = build_msg_pool_reference (offset);
  1108.   TREE_TYPE (expr) = selector_type; /* cast */
  1109.   return expr;
  1110. }
  1111.  
  1112. static void
  1113. build_selector_translation_table ()
  1114. {
  1115.   tree sc_spec, decl_specs, expr_decl;
  1116.   tree chain, initlist = NULLT;
  1117.   int offset = 0;
  1118. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1119.   tree decl, var_decl;
  1120.   int idx = 0;
  1121.   char buf[256];
  1122. #else
  1123.   /* The corresponding pop_obstacks is in finish_decl,
  1124.      called at the end of this function.  */
  1125.   push_obstacks_nochange ();
  1126. #endif
  1127.  
  1128.   for (chain = sel_ref_chain; chain; chain = TREE_CHAIN (chain))
  1129.     {
  1130.       tree expr;
  1131.  
  1132. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1133.       sprintf (buf, "_OBJC_SELECTOR_REFERENCES_%d", idx);
  1134.       sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
  1135.  
  1136.       /* static SEL _OBJC_SELECTOR_REFERENCES_n = ...; */
  1137.       decl_specs = tree_cons (NULLT, selector_type, sc_spec);
  1138.       var_decl = get_identifier (buf);
  1139.  
  1140.       /* the `decl' that is returned from start_decl is the one that we
  1141.     * forward declared in `build_selector_reference()'
  1142.     */
  1143.       decl = start_decl (var_decl, decl_specs, 1); 
  1144. #endif
  1145.  
  1146.       expr = init_selector (offset);
  1147.  
  1148.       /* add one for the '\0' character */
  1149.       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
  1150.  
  1151. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  1152.       finish_decl (decl, expr, NULLT);
  1153.       idx++;
  1154. #else
  1155.       initlist = tree_cons (NULLT, expr, initlist);
  1156. #endif
  1157.     }
  1158.  
  1159. #ifdef OBJC_SELECTORS_WITHOUT_LABELS
  1160.   /* NULL terminate the list and fix the decl for output. */
  1161.   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  1162.   DECL_INITIAL (_OBJC_SELECTOR_REFERENCES_decl) = (tree) 1;
  1163.   DECL_EXTERNAL (_OBJC_SELECTOR_REFERENCES_decl) = 0;
  1164.   TREE_STATIC (_OBJC_SELECTOR_REFERENCES_decl) = 1;
  1165.   initlist = build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  1166.   finish_decl (_OBJC_SELECTOR_REFERENCES_decl, initlist, NULLT);
  1167. #endif
  1168. }
  1169.  
  1170. static void
  1171. add_class_reference (ident)
  1172.      tree ident;
  1173. {
  1174.   tree chain;
  1175.  
  1176.   if (chain = cls_ref_chain)
  1177.     {
  1178.       tree tail;
  1179.       do
  1180.         {
  1181.       if (ident == TREE_VALUE (chain))
  1182.         return;
  1183.  
  1184.       tail = chain;
  1185.       chain = TREE_CHAIN (chain);
  1186.         }
  1187.       while (chain);
  1188.  
  1189.       /* append to the end of the list */
  1190.       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
  1191.     }
  1192.   else
  1193.     cls_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
  1194. }
  1195.  
  1196. /*
  1197.  * sel_ref_chain is a list whose "value" fields will be instances of
  1198.  * identifier_node that represent the selector.
  1199.  */
  1200. static int
  1201. add_selector_reference (ident)
  1202.      tree ident;
  1203. {
  1204.   tree chain;
  1205.   int index = 0;
  1206.  
  1207.   /* this adds it to sel_refdef_chain, the global pool of selectors */
  1208.   add_objc_string (ident);
  1209.  
  1210.   if (chain = sel_ref_chain)
  1211.     {
  1212.       tree tail;
  1213.       do
  1214.         {
  1215.       if (ident == TREE_VALUE (chain))
  1216.         return index;
  1217.  
  1218.       index++;
  1219.       tail = chain;
  1220.       chain = TREE_CHAIN (chain);
  1221.         }
  1222.       while (chain);
  1223.  
  1224.       /* append to the end of the list */
  1225.       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
  1226.     }
  1227.   else
  1228.     sel_ref_chain = perm_tree_cons (NULLT, ident, NULLT);
  1229.  
  1230.   max_selector_index++;
  1231.   return index;
  1232. }
  1233.  
  1234. /*
  1235.  * sel_refdef_chain is a list whose "value" fields will be instances of
  1236.  * identifier_node that represent the selector. It returns the offset of
  1237.  * the selector from the beginning of the _OBJC_STRINGS pool. This offset
  1238.  * is typically used by "init_selector ()" during code generation.
  1239.  */
  1240. static int
  1241. add_objc_string (ident)
  1242.      tree ident;
  1243. {
  1244.   tree chain;
  1245.   int offset = 0;
  1246.  
  1247.   if (chain = sel_refdef_chain)
  1248.     {
  1249.       tree tail;
  1250.       do
  1251.         {
  1252.       if (ident == TREE_VALUE (chain))
  1253.         return offset;
  1254.  
  1255.       /* add one for the '\0' character */
  1256.       offset += IDENTIFIER_LENGTH (TREE_VALUE (chain)) + 1;
  1257.       tail = chain;
  1258.       chain = TREE_CHAIN (chain);
  1259.         }
  1260.       while (chain);
  1261.  
  1262.       /* append to the end of the list */
  1263.       TREE_CHAIN (tail) = perm_tree_cons (NULLT, ident, NULLT);
  1264.     }
  1265.   else
  1266.     sel_refdef_chain = perm_tree_cons (NULLT, ident, NULLT);
  1267.  
  1268.   return offset;
  1269. }
  1270.  
  1271. tree
  1272. lookup_interface (ident)
  1273.      tree ident;
  1274. {
  1275.   tree chain;
  1276.  
  1277.   for (chain = interface_chain; chain; chain = TREE_CHAIN (chain))
  1278.     {
  1279.       if (ident == CLASS_NAME (chain))
  1280.     return chain;
  1281.     }
  1282.   return NULLT;
  1283. }
  1284.  
  1285. static tree
  1286. objc_copy_list (list, head)
  1287.      tree list;
  1288.      tree *head;
  1289. {
  1290.   tree newlist = NULL_TREE, tail = NULL_TREE;
  1291.  
  1292.   while (list)
  1293.     {
  1294.       tail = copy_node (list);
  1295.  
  1296.       /* the following statement fixes a bug when inheriting instance
  1297.      variables that are declared to be bitfields. finish_struct () expects
  1298.      to find the width of the bitfield in DECL_INITIAL (), which it
  1299.      nulls out after processing the decl of the super class...rather
  1300.      than change the way finish_struct () works (which is risky),
  1301.      I create the situation it expects...s.naroff (7/23/89).
  1302.      */
  1303.       if (DECL_BIT_FIELD (tail) && DECL_INITIAL (tail) == 0)
  1304.     DECL_INITIAL (tail) = build_int_2 (DECL_FIELD_SIZE (tail), 0);
  1305.  
  1306.       newlist = chainon (newlist, tail);
  1307.       list = TREE_CHAIN (list);
  1308.     }
  1309.   *head = newlist;
  1310.   return tail;
  1311. }
  1312.  
  1313. /* used by:
  1314.  * build_private_template (), get_class_ivars (), and get_static_reference ().
  1315.  */
  1316. static tree
  1317. build_ivar_chain (interface)
  1318.      tree interface;
  1319. {
  1320.   tree my_name, super_name, ivar_chain;
  1321.  
  1322.   my_name = CLASS_NAME (interface);
  1323.   super_name = CLASS_SUPER_NAME (interface);
  1324.  
  1325.   /* "leaf" ivars never get copied...there is no reason to. */
  1326.   ivar_chain = CLASS_IVARS (interface);
  1327.  
  1328.   while (super_name)
  1329.     {
  1330.       tree op1;
  1331.       tree super_interface = lookup_interface (super_name);
  1332.  
  1333.       if (!super_interface)
  1334.         {
  1335.       /* fatal did not work with 2 args...should fix */
  1336.       error ("Cannot find interface declaration for `%s', superclass of `%s'",
  1337.          IDENTIFIER_POINTER (super_name), IDENTIFIER_POINTER (my_name));
  1338.       exit (34);
  1339.         }
  1340.       if (super_interface == interface)
  1341.         {
  1342.           fatal ("Circular inheritance in interface declaration for `%s'",
  1343.                  IDENTIFIER_POINTER (super_name));
  1344.         }
  1345.       interface = super_interface;
  1346.       my_name = CLASS_NAME (interface);
  1347.       super_name = CLASS_SUPER_NAME (interface);
  1348.  
  1349.       op1 = CLASS_IVARS (interface);
  1350.       if (op1)
  1351.         {
  1352.       tree head, tail = objc_copy_list (op1, &head);
  1353.  
  1354.       /* prepend super class ivars...make a copy of the list, we
  1355.        * do not want to alter the original.
  1356.        */
  1357.       TREE_CHAIN (tail) = ivar_chain;
  1358.       ivar_chain = head;
  1359.         }
  1360.     }
  1361.   return ivar_chain;
  1362. }
  1363.  
  1364. /*
  1365.  *  struct <classname> {
  1366.  *    struct objc_class *isa;
  1367.  *    ...
  1368.  *  };
  1369.  */
  1370. static tree
  1371. build_private_template (class)
  1372.      tree class;
  1373. {
  1374.   tree ivar_context;
  1375.  
  1376.   if (CLASS_STATIC_TEMPLATE (class))
  1377.     {
  1378.       _PRIVATE_record = CLASS_STATIC_TEMPLATE (class);
  1379.       ivar_context = TYPE_FIELDS (CLASS_STATIC_TEMPLATE (class));
  1380.     }
  1381.   else
  1382.     {
  1383.       _PRIVATE_record = start_struct (RECORD_TYPE, CLASS_NAME (class));
  1384.  
  1385.       ivar_context = build_ivar_chain (class);
  1386.  
  1387.       finish_struct (_PRIVATE_record, ivar_context);
  1388.  
  1389.       CLASS_STATIC_TEMPLATE (class) = _PRIVATE_record;
  1390.  
  1391.       /* mark this record as class template - for class type checking */
  1392.       TREE_STATIC_TEMPLATE (_PRIVATE_record) = 1;
  1393.     }
  1394.   instance_type = groktypename (
  1395.                 build_tree_list (build_tree_list (NULLT, _PRIVATE_record),
  1396.                          build1 (INDIRECT_REF, NULLT, NULLT)));
  1397.   return ivar_context;
  1398. }
  1399.  
  1400. /*
  1401.  *  struct objc_category {
  1402.  *    char *category_name;
  1403.  *    char *class_name;
  1404.  *    struct objc_method_list *instance_methods;
  1405.  *    struct objc_method_list *class_methods;
  1406.  *  };
  1407.  */
  1408. static void
  1409. build_category_template ()
  1410. {
  1411.   tree decl_specs, field_decl, field_decl_chain;
  1412.  
  1413.   objc_category_template = start_struct (RECORD_TYPE,
  1414.                      get_identifier (_TAG_CATEGORY));
  1415.   /* char *category_name; */
  1416.  
  1417.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
  1418.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("category_name"));
  1419.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1420.   field_decl_chain = field_decl;
  1421.  
  1422.   /* char *class_name; */
  1423.  
  1424.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
  1425.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_name"));
  1426.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1427.   chainon (field_decl_chain, field_decl);
  1428.  
  1429.   /* struct objc_method_list *instance_methods; */
  1430.  
  1431.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  1432.                          get_identifier (_TAG_METHOD_LIST)));
  1433.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("instance_methods"));
  1434.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1435.   chainon (field_decl_chain, field_decl);
  1436.  
  1437.   /* struct objc_method_list *class_methods; */
  1438.  
  1439.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  1440.                          get_identifier (_TAG_METHOD_LIST)));
  1441.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class_methods"));
  1442.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1443.   chainon (field_decl_chain, field_decl);
  1444.  
  1445.   finish_struct (objc_category_template, field_decl_chain);
  1446. }
  1447.  
  1448. /*
  1449.  *  struct objc_class {
  1450.  *    struct objc_class *isa;
  1451.  *    struct objc_class *super_class;
  1452.  *    char *name;
  1453.  *    long version;
  1454.  *    long info;
  1455.  *    long instance_size;
  1456.  *    struct objc_ivar_list *ivars;
  1457.  *    struct objc_method_list *methods;
  1458.  *    struct objc_cache *cache;
  1459.  *  };
  1460.  */
  1461. static void
  1462. build_class_template ()
  1463. {
  1464.   tree decl_specs, field_decl, field_decl_chain;
  1465.  
  1466.   objc_class_template = start_struct (RECORD_TYPE, get_identifier (_TAG_CLASS));
  1467.  
  1468.   /* struct objc_class *isa; */
  1469.  
  1470.   decl_specs = build_tree_list (NULLT, objc_class_template);
  1471.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("isa"));
  1472.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1473.   field_decl_chain = field_decl;
  1474.  
  1475.   /* struct objc_class *super_class; */
  1476.  
  1477.   decl_specs = build_tree_list (NULLT, objc_class_template);
  1478.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("super_class"));
  1479.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1480.   chainon (field_decl_chain, field_decl);
  1481.  
  1482.   /* char *name; */
  1483.  
  1484.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
  1485.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("name"));
  1486.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1487.   chainon (field_decl_chain, field_decl);
  1488.  
  1489.   /* long version; */
  1490.  
  1491.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
  1492.   field_decl = get_identifier ("version");
  1493.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1494.   chainon (field_decl_chain, field_decl);
  1495.  
  1496.   /* long info; */
  1497.  
  1498.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
  1499.   field_decl = get_identifier ("info");
  1500.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1501.   chainon (field_decl_chain, field_decl);
  1502.  
  1503.   /* long instance_size; */
  1504.  
  1505.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_LONG]);
  1506.   field_decl = get_identifier ("instance_size");
  1507.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1508.   chainon (field_decl_chain, field_decl);
  1509.  
  1510.   /* struct objc_ivar_list *ivars; */
  1511.  
  1512.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  1513.                          get_identifier (_TAG_IVAR_LIST)));
  1514.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivars"));
  1515.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1516.   chainon (field_decl_chain, field_decl);
  1517.  
  1518.   /* struct objc_method_list *methods; */
  1519.  
  1520.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  1521.                          get_identifier (_TAG_METHOD_LIST)));
  1522.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("methods"));
  1523.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1524.   chainon (field_decl_chain, field_decl);
  1525.  
  1526.   /* struct objc_cache *cache; */
  1527.  
  1528.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  1529.                          get_identifier ("objc_cache")));
  1530.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("cache"));
  1531.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1532.   chainon (field_decl_chain, field_decl);
  1533.  
  1534.   finish_struct (objc_class_template, field_decl_chain);
  1535. }
  1536.  
  1537. /*
  1538.  * generate appropriate forward declarations for an implementation
  1539.  */
  1540. static void
  1541. synth_forward_declarations ()
  1542. {
  1543.   tree sc_spec, decl_specs, factory_id, anId;
  1544.  
  1545.   /* extern struct objc_class _OBJC_CLASS_<my_name>; */
  1546.  
  1547.   anId = synth_id_with_class_suffix ("_OBJC_CLASS");
  1548.  
  1549.   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
  1550.   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
  1551.   _OBJC_CLASS_decl = define_decl (anId, decl_specs);
  1552.  
  1553.   /* extern struct objc_class _OBJC_METACLASS_<my_name>; */
  1554.  
  1555.   anId = synth_id_with_class_suffix ("_OBJC_METACLASS");
  1556.  
  1557.   _OBJC_METACLASS_decl = define_decl (anId, decl_specs);
  1558.  
  1559.   /* pre-build the following entities - for speed/convenience. */
  1560.  
  1561.   anId = get_identifier ("super_class");
  1562.   _clsSuper_ref = build_component_ref (_OBJC_CLASS_decl, anId);
  1563.   __clsSuper_ref = build_component_ref (_OBJC_METACLASS_decl, anId);
  1564. }
  1565.  
  1566. static void
  1567. error_with_ivar (message, decl, rawdecl)
  1568.      char *message;
  1569.      tree decl;
  1570.      tree rawdecl;
  1571. {
  1572.   count_error (0);
  1573.   fprintf (stderr, "%s:%d: ",
  1574.        DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
  1575.   bzero (errbuf, BUFSIZE);
  1576.   fprintf (stderr, "%s `%s'\n", message, gen_declaration (rawdecl, errbuf));
  1577. }
  1578.  
  1579. #define USERTYPE(t)    (TREE_CODE (t) == RECORD_TYPE || \
  1580.              TREE_CODE (t) == UNION_TYPE ||  \
  1581.              TREE_CODE (t) == ENUMERAL_TYPE)
  1582.  
  1583. static void
  1584. check_ivars (inter, imp)
  1585.      tree inter;
  1586.      tree imp;
  1587. {
  1588.   tree intdecls = CLASS_IVARS (inter);
  1589.   tree impdecls = CLASS_IVARS (imp);
  1590.   tree rawintdecls = CLASS_RAW_IVARS (inter);
  1591.   tree rawimpdecls = CLASS_RAW_IVARS (imp);
  1592.  
  1593.   while (1)
  1594.     {
  1595.       tree t1, t2;
  1596.  
  1597.       if (intdecls == 0 && impdecls == 0)
  1598.     break;
  1599.       if (intdecls == 0 || impdecls == 0)
  1600.     {
  1601.       error ("inconsistent instance variable specification");
  1602.       break;
  1603.     }
  1604.       t1 = TREE_TYPE (intdecls); t2 = TREE_TYPE (impdecls);
  1605.  
  1606.       if (!comptypes (t1, t2))
  1607.     {
  1608.       if (DECL_NAME (intdecls) == DECL_NAME (impdecls))
  1609.         {
  1610.           error_with_ivar ("conflicting instance variable type",
  1611.                    impdecls, rawimpdecls);
  1612.           error_with_ivar ("previous declaration of",
  1613.                    intdecls, rawintdecls);
  1614.         }
  1615.       else            /* both the type and the name don't match */
  1616.         {
  1617.           error ("inconsistent instance variable specification");
  1618.           break;
  1619.         }
  1620.     }
  1621.       else if (DECL_NAME (intdecls) != DECL_NAME (impdecls))
  1622.     {
  1623.       error_with_ivar ("conflicting instance variable name",
  1624.                impdecls, rawimpdecls);
  1625.       error_with_ivar ("previous declaration of",
  1626.                intdecls, rawintdecls);
  1627.     }
  1628.       intdecls = TREE_CHAIN (intdecls);
  1629.       impdecls = TREE_CHAIN (impdecls);
  1630.       rawintdecls = TREE_CHAIN (rawintdecls);
  1631.       rawimpdecls = TREE_CHAIN (rawimpdecls);
  1632.     }
  1633. }
  1634.  
  1635. /*
  1636.  *     struct objc_super {
  1637.  *        id self;
  1638.  *        struct objc_class *class;
  1639.  *    };
  1640.  */
  1641. static tree
  1642. build_super_template ()
  1643. {
  1644.   tree record, decl_specs, field_decl, field_decl_chain;
  1645.  
  1646.   record = start_struct (RECORD_TYPE, get_identifier (_TAG_SUPER));
  1647.  
  1648.   /* struct objc_object *self; */
  1649.  
  1650.   decl_specs = build_tree_list (NULLT, objc_object_reference);
  1651.   field_decl = get_identifier ("self");
  1652.   field_decl = build1 (INDIRECT_REF, NULLT, field_decl);
  1653.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1654.   field_decl_chain = field_decl;
  1655.  
  1656.   /* struct objc_class *class; */
  1657.  
  1658.   decl_specs = get_identifier (_TAG_CLASS);
  1659.   decl_specs = build_tree_list (NULLT, xref_tag (RECORD_TYPE, decl_specs));
  1660.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("class"));
  1661.  
  1662.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1663.   chainon (field_decl_chain, field_decl);
  1664.  
  1665.   finish_struct (record, field_decl_chain);
  1666.  
  1667.   /* `struct objc_super *' */
  1668.   super_type = groktypename (build_tree_list (build_tree_list (NULLT, record),
  1669.                           build1 (INDIRECT_REF, NULLT, NULLT)));
  1670.   return record;
  1671. }
  1672.  
  1673. /*
  1674.  *     struct objc_ivar {
  1675.  *        char *ivar_name;
  1676.  *        char *ivar_type;
  1677.  *        int ivar_offset;
  1678.  *    };
  1679.  */
  1680. static tree
  1681. build_ivar_template ()
  1682. {
  1683.   tree objc_ivar_id, objc_ivar_record;
  1684.   tree decl_specs, field_decl, field_decl_chain;
  1685.  
  1686.   objc_ivar_id = get_identifier (_TAG_IVAR);
  1687.   objc_ivar_record = start_struct (RECORD_TYPE, objc_ivar_id);
  1688.  
  1689.   /* char *ivar_name; */
  1690.  
  1691.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
  1692.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_name"));
  1693.  
  1694.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1695.   field_decl_chain = field_decl;
  1696.  
  1697.   /* char *ivar_type; */
  1698.  
  1699.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_CHAR]);
  1700.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("ivar_type"));
  1701.  
  1702.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1703.   chainon (field_decl_chain, field_decl);
  1704.  
  1705.   /* int ivar_offset; */
  1706.  
  1707.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
  1708.   field_decl = get_identifier ("ivar_offset");
  1709.  
  1710.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1711.   chainon (field_decl_chain, field_decl);
  1712.  
  1713.   finish_struct (objc_ivar_record, field_decl_chain);
  1714.  
  1715.   return objc_ivar_record;
  1716. }
  1717.  
  1718. /*
  1719.  *     struct {
  1720.  *        int ivar_count;
  1721.  *        struct objc_ivar ivar_list[ivar_count];
  1722.  *    };
  1723.  */
  1724. static tree
  1725. build_ivar_list_template (list_type, size)
  1726.      tree list_type;
  1727.      int size;
  1728. {
  1729.   tree objc_ivar_list_id, objc_ivar_list_record;
  1730.   tree decl_specs, field_decl, field_decl_chain;
  1731.  
  1732.   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
  1733.  
  1734.   /* int ivar_count; */
  1735.  
  1736.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
  1737.   field_decl = get_identifier ("ivar_count");
  1738.  
  1739.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1740.   field_decl_chain = field_decl;
  1741.  
  1742.   /* struct objc_ivar ivar_list[]; */
  1743.  
  1744.   decl_specs = build_tree_list (NULLT, list_type);
  1745.   field_decl = build_nt (ARRAY_REF, get_identifier ("ivar_list"),
  1746.              build_int_2 (size, 0));
  1747.  
  1748.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1749.   chainon (field_decl_chain, field_decl);
  1750.  
  1751.   finish_struct (objc_ivar_list_record, field_decl_chain);
  1752.  
  1753.   return objc_ivar_list_record;
  1754. }
  1755.  
  1756. /*
  1757.  *     struct {
  1758.  *        int method_next;
  1759.  *        int method_count;
  1760.  *        struct objc_method method_list[method_count];
  1761.  *    };
  1762.  */
  1763. static tree
  1764. build_method_list_template (list_type, size)
  1765.      tree list_type;
  1766.      int size;
  1767. {
  1768.   tree objc_ivar_list_id, objc_ivar_list_record;
  1769.   tree decl_specs, field_decl, field_decl_chain;
  1770.  
  1771.   objc_ivar_list_record = start_struct (RECORD_TYPE, NULLT);
  1772.  
  1773.   /* int method_next; */
  1774.  
  1775.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
  1776.   field_decl = get_identifier ("method_next");
  1777.  
  1778.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1779.   field_decl_chain = field_decl;
  1780.  
  1781.   /* int method_count; */
  1782.  
  1783.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_INT]);
  1784.   field_decl = get_identifier ("method_count");
  1785.  
  1786.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1787.   chainon (field_decl_chain, field_decl);
  1788.  
  1789.   /* struct objc_method method_list[]; */
  1790.  
  1791.   decl_specs = build_tree_list (NULLT, list_type);
  1792.   field_decl = build_nt (ARRAY_REF, get_identifier ("method_list"),
  1793.              build_int_2 (size, 0));
  1794.  
  1795.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1796.   chainon (field_decl_chain, field_decl);
  1797.  
  1798.   finish_struct (objc_ivar_list_record, field_decl_chain);
  1799.  
  1800.   return objc_ivar_list_record;
  1801. }
  1802.  
  1803. static tree
  1804. build_ivar_list_initializer (field_decl, size)
  1805.      tree field_decl;
  1806.      int *size;
  1807. {
  1808.   tree initlist = NULLT;
  1809.  
  1810.   do
  1811.     {
  1812.       int offset;
  1813.  
  1814.     /* set name */
  1815.     if (DECL_NAME (field_decl))
  1816.       {
  1817.         offset = add_objc_string (DECL_NAME (field_decl));
  1818.         initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
  1819.       }
  1820.     else
  1821.       {
  1822.         /* unnamed bit-field ivar (yuck). */
  1823.         initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  1824.       }
  1825.  
  1826.       /* set type */
  1827.       encode_field_decl (field_decl, OBJC_ENCODE_DONT_INLINE_DEFS);
  1828.       offset = add_objc_string (get_identifier (obstack_finish (&util_obstack)));
  1829.       obstack_free (&util_obstack, util_firstobj);
  1830.  
  1831.       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
  1832.  
  1833.       /* set offset */
  1834.       initlist = tree_cons (NULLT,
  1835.                 build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field_decl)) / BITS_PER_UNIT, 0),
  1836.                 
  1837.                 initlist);
  1838.       (*size)++;
  1839.       field_decl = TREE_CHAIN (field_decl);
  1840.     }
  1841.   while (field_decl);
  1842.  
  1843.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  1844. }
  1845.  
  1846. static tree
  1847. generate_ivars_list (type, name, size, list)
  1848.      tree type;
  1849.      char *name;
  1850.      int size;
  1851.      tree list;
  1852. {
  1853.   tree sc_spec, decl_specs, decl, initlist;
  1854.  
  1855.   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
  1856.   decl_specs = tree_cons (NULLT, type, sc_spec);
  1857.  
  1858.   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
  1859.  
  1860.   initlist = build_tree_list (NULLT, build_int_2 (size, 0));
  1861.   initlist = tree_cons (NULLT, list, initlist);
  1862.  
  1863.   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
  1864.  
  1865.   return decl;
  1866. }
  1867.  
  1868. static void
  1869. generate_ivar_lists ()
  1870. {
  1871.   tree initlist, ivar_list_template, chain;
  1872.   tree cast, variable_length_type;
  1873.   int size;
  1874.  
  1875.   if (!objc_ivar_template)
  1876.     objc_ivar_template = build_ivar_template ();
  1877.  
  1878.   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  1879.                                 get_identifier (_TAG_IVAR_LIST))), NULLT);
  1880.   variable_length_type = groktypename (cast);
  1881.  
  1882.   /* only generate class variables for the root of the inheritance
  1883.      hierarchy since these will be the same for every class */
  1884.  
  1885.   if (CLASS_SUPER_NAME (implementation_template) == NULLT
  1886.       && (chain = TYPE_FIELDS (objc_class_template)))
  1887.     {
  1888.       size = 0;
  1889.       initlist = build_ivar_list_initializer (chain, &size);
  1890.  
  1891.       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
  1892.  
  1893.       _OBJC_CLASS_VARIABLES_decl =
  1894.     generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES",
  1895.                  size, initlist);
  1896.       /* cast! */
  1897.       TREE_TYPE (_OBJC_CLASS_VARIABLES_decl) = variable_length_type;
  1898.     }
  1899.   else
  1900.     _OBJC_CLASS_VARIABLES_decl = 0;
  1901.  
  1902.   chain = CLASS_IVARS (implementation_template);
  1903.   if (chain)
  1904.     {
  1905.       size = 0;
  1906.       initlist = build_ivar_list_initializer (chain, &size);
  1907.  
  1908.       ivar_list_template = build_ivar_list_template (objc_ivar_template, size);
  1909.  
  1910.       _OBJC_INSTANCE_VARIABLES_decl =
  1911.     generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES",
  1912.                  size, initlist);
  1913.       /* cast! */
  1914.       TREE_TYPE (_OBJC_INSTANCE_VARIABLES_decl) = variable_length_type;
  1915.     }
  1916.   else
  1917.     _OBJC_INSTANCE_VARIABLES_decl = 0;
  1918. }
  1919.  
  1920. static tree
  1921. build_dispatch_table_initializer (entries, size)
  1922.      tree entries;
  1923.      int *size;
  1924. {
  1925.   tree initlist = NULLT;
  1926.  
  1927.   do
  1928.     {
  1929.       int offset = add_objc_string (METHOD_SEL_NAME (entries));
  1930.  
  1931.       initlist = tree_cons (NULLT, init_selector (offset), initlist);
  1932.  
  1933.       offset = add_objc_string (METHOD_ENCODING (entries));
  1934.       initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist);
  1935.  
  1936.       initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist);
  1937.  
  1938.       (*size)++;
  1939.       entries = TREE_CHAIN (entries);
  1940.     }
  1941.   while (entries);
  1942.  
  1943.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  1944. }
  1945.  
  1946. /*
  1947.  * To accomplish method prototyping without generating all kinds of
  1948.  * inane warnings, the definition of the dispatch table entries were
  1949.  * changed from:
  1950.  *
  1951.  *     struct objc_method { SEL _cmd; id (*_imp)(); };
  1952.  * to:
  1953.  *     struct objc_method { SEL _cmd; void *_imp; };
  1954.  */
  1955. static tree
  1956. build_method_template ()
  1957. {
  1958.   tree _SLT_record;
  1959.   tree decl_specs, field_decl, field_decl_chain, parms;
  1960.  
  1961.   _SLT_record = start_struct (RECORD_TYPE, get_identifier (_TAG_METHOD));
  1962.  
  1963. #ifdef OBJC_INT_SELECTORS
  1964.   /* unsigned int _cmd; */
  1965.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT);
  1966.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
  1967.   field_decl = get_identifier ("_cmd");
  1968. #else /* not OBJC_INT_SELECTORS */
  1969.   /* struct objc_selector *_cmd; */
  1970.   decl_specs = tree_cons (NULLT,
  1971.               xref_tag (RECORD_TYPE,
  1972.                     get_identifier (TAG_SELECTOR)),
  1973.               NULLT);
  1974.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));
  1975. #endif /* not OBJC_INT_SELECTORS */
  1976.  
  1977.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1978.   field_decl_chain = field_decl;
  1979.  
  1980.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT);
  1981.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types"));
  1982.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1983.   chainon (field_decl_chain, field_decl);
  1984.  
  1985.   /* void *_imp; */
  1986.  
  1987.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT);
  1988.   field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp"));
  1989.   field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT);
  1990.   chainon (field_decl_chain, field_decl);
  1991.  
  1992.   finish_struct (_SLT_record, field_decl_chain);
  1993.  
  1994.   return _SLT_record;
  1995. }
  1996.  
  1997.  
  1998. static tree
  1999. generate_dispatch_table (type, name, size, list)
  2000.      tree type;
  2001.      char *name;
  2002.      int size;
  2003.      tree list;
  2004. {
  2005.   tree sc_spec, decl_specs, decl, initlist;
  2006.  
  2007.   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
  2008.   decl_specs = tree_cons (NULLT, type, sc_spec);
  2009.  
  2010.   decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1);
  2011.  
  2012.   initlist = build_tree_list (NULLT, build_int_2 (0, 0));
  2013.   initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist);
  2014.   initlist = tree_cons (NULLT, list, initlist);
  2015.  
  2016.   finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT);
  2017.  
  2018.   return decl;
  2019. }
  2020.  
  2021. static void
  2022. generate_dispatch_tables ()
  2023. {
  2024.   tree initlist, chain, method_list_template;
  2025.   tree cast, variable_length_type;
  2026.   int size;
  2027.  
  2028.   if (!objc_method_template)
  2029.     objc_method_template = build_method_template ();
  2030.  
  2031.   cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE,
  2032.                                 get_identifier (_TAG_METHOD_LIST))), NULLT);
  2033.   variable_length_type = groktypename (cast);
  2034.  
  2035.   chain = CLASS_CLS_METHODS (implementation_context);
  2036.   if (chain)
  2037.     {
  2038.       size = 0;
  2039.       initlist = build_dispatch_table_initializer (chain, &size);
  2040.  
  2041.       method_list_template = build_method_list_template (objc_method_template,
  2042.                              size);
  2043.       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  2044.     _OBJC_CLASS_METHODS_decl = 
  2045.         generate_dispatch_table (method_list_template,
  2046.                      "_OBJC_CLASS_METHODS", 
  2047.                      size, initlist);
  2048.       else
  2049.     /* we have a category */
  2050.     _OBJC_CLASS_METHODS_decl = 
  2051.         generate_dispatch_table (method_list_template,
  2052.                      "_OBJC_CATEGORY_CLASS_METHODS", 
  2053.                      size, initlist);
  2054.       /* cast! */
  2055.       TREE_TYPE (_OBJC_CLASS_METHODS_decl) = variable_length_type;
  2056.     }
  2057.   else
  2058.     _OBJC_CLASS_METHODS_decl = 0;
  2059.  
  2060.   chain = CLASS_NST_METHODS (implementation_context);
  2061.   if (chain)
  2062.     {
  2063.       size = 0;
  2064.       initlist = build_dispatch_table_initializer (chain, &size);
  2065.  
  2066.       method_list_template = build_method_list_template (objc_method_template,
  2067.                              size);
  2068.       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  2069.     _OBJC_INSTANCE_METHODS_decl = 
  2070.         generate_dispatch_table (method_list_template,
  2071.                      "_OBJC_INSTANCE_METHODS", 
  2072.                      size, initlist);
  2073.       else
  2074.     /* we have a category */
  2075.     _OBJC_INSTANCE_METHODS_decl = 
  2076.         generate_dispatch_table (method_list_template,
  2077.                      "_OBJC_CATEGORY_INSTANCE_METHODS", 
  2078.                      size, initlist);
  2079.       /* cast! */
  2080.       TREE_TYPE (_OBJC_INSTANCE_METHODS_decl) = variable_length_type;
  2081.     }
  2082.   else
  2083.     _OBJC_INSTANCE_METHODS_decl = 0;
  2084. }
  2085.  
  2086. static tree
  2087. build_category_initializer (cat_name, class_name,
  2088.                 instance_methods, class_methods)
  2089.      tree cat_name;
  2090.      tree class_name;
  2091.      tree instance_methods;
  2092.      tree class_methods;
  2093. {
  2094.   tree initlist = NULLT, expr;
  2095.  
  2096.   initlist = tree_cons (NULLT, cat_name, initlist);
  2097.   initlist = tree_cons (NULLT, class_name, initlist);
  2098.  
  2099.   if (!instance_methods)
  2100.     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  2101.   else
  2102.     {
  2103.       expr = build_unary_op (ADDR_EXPR, instance_methods, 0);
  2104.       initlist = tree_cons (NULLT, expr, initlist);
  2105.     }
  2106.   if (!class_methods)
  2107.     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  2108.   else
  2109.     {
  2110.       expr = build_unary_op (ADDR_EXPR, class_methods, 0);
  2111.       initlist = tree_cons (NULLT, expr, initlist);
  2112.     }
  2113.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  2114. }
  2115.  
  2116. /*
  2117.  *  struct objc_class {
  2118.  *    struct objc_class *isa;
  2119.  *    struct objc_class *super_class;
  2120.  *    char *name;
  2121.  *    long version;
  2122.  *    long info;
  2123.  *    long instance_size;
  2124.  *    struct objc_ivar_list *ivars;
  2125.  *    struct objc_method_list *methods;
  2126.  *    struct objc_cache *cache;
  2127.  *  };
  2128.  */
  2129. static tree
  2130. build_shared_structure_initializer (isa, super, name, size, status,
  2131.                     dispatch_table, ivar_list)
  2132.      tree isa;
  2133.      tree super;
  2134.      tree name;
  2135.      tree size;
  2136.      int status;
  2137.      tree dispatch_table;
  2138.      tree ivar_list;
  2139. {
  2140.   tree initlist = NULLT, expr;
  2141.  
  2142.   /* isa = */
  2143.   initlist = tree_cons (NULLT, isa, initlist);
  2144.  
  2145.   /* super_class = */
  2146.   initlist = tree_cons (NULLT, super, initlist);
  2147.  
  2148.   /* name = */
  2149.   initlist = tree_cons (NULLT, name, initlist);
  2150.  
  2151.   /* version = */
  2152.   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  2153.  
  2154.   /* info = */
  2155.   initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist);
  2156.  
  2157.   /* instance_size = */
  2158.   initlist = tree_cons (NULLT, size, initlist);
  2159.  
  2160.   /* objc_ivar_list = */
  2161.   if (!ivar_list)
  2162.     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  2163.   else
  2164.     {
  2165.       expr = build_unary_op (ADDR_EXPR, ivar_list, 0);
  2166.       initlist = tree_cons (NULLT, expr, initlist);
  2167.     }
  2168.  
  2169.   /* objc_method_list = */
  2170.   if (!dispatch_table)
  2171.     initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  2172.   else
  2173.     {
  2174.       expr = build_unary_op (ADDR_EXPR, dispatch_table, 0);
  2175.       initlist = tree_cons (NULLT, expr, initlist);
  2176.     }
  2177.  
  2178.   /* method_cache = */
  2179.   initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist);
  2180.  
  2181.   return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));
  2182. }
  2183.  
  2184. /*
  2185.  * static struct objc_category _OBJC_CATEGORY_<name> = { ... };
  2186.  */
  2187. static void
  2188. generate_category (cat)
  2189.      tree cat;
  2190. {
  2191.   tree sc_spec, decl_specs, decl;
  2192.   tree initlist, cat_name_expr, class_name_expr;
  2193.   int offset;
  2194.  
  2195.   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
  2196.   decl_specs = tree_cons (NULLT, objc_category_template, sc_spec);
  2197.  
  2198.   decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY"),
  2199.              decl_specs, 1);
  2200.  
  2201.   offset = add_objc_string (CLASS_SUPER_NAME (cat));
  2202.   cat_name_expr = build_msg_pool_reference (offset);
  2203.  
  2204.   offset = add_objc_string (CLASS_NAME (cat));
  2205.   class_name_expr = build_msg_pool_reference (offset);
  2206.  
  2207.   initlist = build_category_initializer (
  2208.                      cat_name_expr, class_name_expr,
  2209.                      _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl);
  2210.  
  2211.   finish_decl (decl, initlist, NULLT);
  2212. }
  2213.  
  2214. /*
  2215.  * static struct objc_class _OBJC_METACLASS_Foo={ ... };
  2216.  * static struct objc_class _OBJC_CLASS_Foo={ ... };
  2217.  */
  2218. static void
  2219. generate_shared_structures ()
  2220. {
  2221.   tree sc_spec, decl_specs, expr_decl, decl;
  2222.   tree name_expr, super_expr, root_expr;
  2223.   tree my_root_id = NULLT, my_super_id = NULLT;
  2224.   tree cast_type, initlist;
  2225.   int offset;
  2226.  
  2227.   my_super_id = CLASS_SUPER_NAME (implementation_template);
  2228.   if (my_super_id)
  2229.     {
  2230.       add_class_reference (my_super_id);
  2231.  
  2232.       /* compute "my_root_id" - this is required for code generation.
  2233.        * the "isa" for all meta class structures points to the root of
  2234.        * the inheritance hierarchy (e.g. "__Object")...
  2235.        */
  2236.       my_root_id = my_super_id;
  2237.       do
  2238.     {
  2239.       tree my_root_int = lookup_interface (my_root_id);
  2240.  
  2241.       if (my_root_int && CLASS_SUPER_NAME (my_root_int))
  2242.         my_root_id = CLASS_SUPER_NAME (my_root_int);
  2243.       else
  2244.         break;
  2245.     }
  2246.       while (1);
  2247.     }
  2248.   else                /* no super class */
  2249.     {
  2250.       my_root_id = CLASS_NAME (implementation_template);
  2251.     }
  2252.  
  2253.   cast_type = groktypename (build_tree_list (build_tree_list (NULLT,
  2254.                                   objc_class_template), build1 (INDIRECT_REF, NULLT, NULLT)));
  2255.  
  2256.   offset = add_objc_string (CLASS_NAME (implementation_template));
  2257.   name_expr = build_msg_pool_reference (offset);
  2258.  
  2259.   /* install class `isa' and `super' pointers at runtime */
  2260.   if (my_super_id)
  2261.     {
  2262.       offset = add_objc_string (my_super_id);
  2263.       super_expr = build_msg_pool_reference (offset);
  2264.       TREE_TYPE (super_expr) = cast_type; /* cast! */
  2265.     }
  2266.   else
  2267.     super_expr = build_int_2 (0, 0);
  2268.  
  2269.   offset = add_objc_string (my_root_id);
  2270.   root_expr = build_msg_pool_reference (offset);
  2271.   TREE_TYPE (root_expr) = cast_type; /* cast! */
  2272.  
  2273.   /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */
  2274.  
  2275.   sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]);
  2276.   decl_specs = tree_cons (NULLT, objc_class_template, sc_spec);
  2277.  
  2278.   decl = start_decl (DECL_NAME (_OBJC_METACLASS_decl), decl_specs, 1);
  2279.  
  2280.   initlist = build_shared_structure_initializer (
  2281.                          root_expr, super_expr, name_expr,
  2282.                          build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) / BITS_PER_UNIT, 0),
  2283.                          2 /*CLS_META*/,
  2284.                          _OBJC_CLASS_METHODS_decl, _OBJC_CLASS_VARIABLES_decl);
  2285.  
  2286.   finish_decl (decl, initlist, NULLT);
  2287.  
  2288.   /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */
  2289.  
  2290.   decl = start_decl (DECL_NAME (_OBJC_CLASS_decl), decl_specs, 1);
  2291.  
  2292.   initlist = build_shared_structure_initializer (
  2293.                          build_unary_op (ADDR_EXPR, _OBJC_METACLASS_decl, 0),
  2294.                          super_expr, name_expr,
  2295.                          build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) / BITS_PER_UNIT, 0),
  2296.                          1 /*CLS_FACTORY*/,
  2297.                          _OBJC_INSTANCE_METHODS_decl, _OBJC_INSTANCE_VARIABLES_decl);
  2298.  
  2299.   finish_decl (decl, initlist, NULLT);
  2300. }
  2301.  
  2302. static tree
  2303. synth_id_with_class_suffix (preamble)
  2304.      char *preamble;
  2305. {
  2306.   char *string;
  2307.   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  2308.     {
  2309.       string = (char *) alloca (strlen (preamble)
  2310.                 + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
  2311.                 + 3);
  2312.       sprintf (string, "%s_%s", preamble,
  2313.            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
  2314.     }
  2315.   else
  2316.     {
  2317.       /* we have a category */
  2318.       string = (char *) alloca (strlen (preamble)
  2319.                 + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context)))
  2320.                 + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
  2321.                 + 3);
  2322.       sprintf (string, "%s_%s_%s", preamble,
  2323.            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
  2324.            IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
  2325.     }
  2326.   return get_identifier (string);
  2327. }
  2328.  
  2329. /*
  2330.  *   usage:
  2331.  *        keyworddecl:
  2332.  *            selector ':' '(' typename ')' identifier
  2333.  *
  2334.  *   purpose:
  2335.  *        transform an Objective-C keyword argument into
  2336.  *        the C equivalent parameter declarator.
  2337.  *
  2338.  *   in:    key_name, an "identifier_node" (optional).
  2339.  *        arg_type, a  "tree_list" (optional).
  2340.  *        arg_name, an "identifier_node".
  2341.  *
  2342.  *   note:    it would be really nice to strongly type the preceding
  2343.  *        arguments in the function prototype; however, then i
  2344.  *        could not use the "accessor" macros defined in "tree.h".
  2345.  *
  2346.  *   out:    an instance of "keyword_decl".
  2347.  *
  2348.  */
  2349.  
  2350. tree
  2351. build_keyword_decl (key_name, arg_type, arg_name)
  2352.      tree key_name;
  2353.      tree arg_type;
  2354.      tree arg_name;
  2355. {
  2356.   tree keyword_decl;
  2357.  
  2358.   /* if no type is specified, default to "id" */
  2359.   if (arg_type == NULLT)
  2360.     arg_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
  2361.                 build1 (INDIRECT_REF, NULLT, NULLT));
  2362.  
  2363.   keyword_decl = make_node (KEYWORD_DECL);
  2364.  
  2365.   TREE_TYPE (keyword_decl) = arg_type;
  2366.   KEYWORD_ARG_NAME (keyword_decl) = arg_name;
  2367.   KEYWORD_KEY_NAME (keyword_decl) = key_name;
  2368.  
  2369.   return keyword_decl;
  2370. }
  2371.  
  2372. /*
  2373.  *  given a chain of keyword_decl's, synthesize the full keyword selector.
  2374.  */
  2375. static tree
  2376. build_keyword_selector (selector)
  2377.      tree selector;
  2378. {
  2379.   int len = 0;
  2380.   tree key_chain, key_name;
  2381.   char *buf;
  2382.  
  2383.   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
  2384.     {
  2385.       if (TREE_CODE (selector) == KEYWORD_DECL)
  2386.     key_name = KEYWORD_KEY_NAME (key_chain);
  2387.       else if (TREE_CODE (selector) == TREE_LIST)
  2388.     key_name = TREE_PURPOSE (key_chain);
  2389.  
  2390.       if (key_name)
  2391.     len += IDENTIFIER_LENGTH (key_name) + 1;
  2392.       else            /* just a ':' arg */
  2393.     len++;
  2394.     }
  2395.   buf = (char *)alloca (len + 1);
  2396.   bzero (buf, len + 1);
  2397.  
  2398.   for (key_chain = selector; key_chain; key_chain = TREE_CHAIN (key_chain))
  2399.     {
  2400.       if (TREE_CODE (selector) == KEYWORD_DECL)
  2401.     key_name = KEYWORD_KEY_NAME (key_chain);
  2402.       else if (TREE_CODE (selector) == TREE_LIST)
  2403.     key_name = TREE_PURPOSE (key_chain);
  2404.  
  2405.       if (key_name)
  2406.     strcat (buf, IDENTIFIER_POINTER (key_name));
  2407.       strcat (buf, ":");
  2408.     }
  2409.   return get_identifier (buf);
  2410. }
  2411.  
  2412. /* used for declarations and definitions */
  2413.  
  2414. tree
  2415. build_method_decl (code, ret_type, selector, add_args)
  2416.      enum tree_code code;
  2417.      tree ret_type;
  2418.      tree selector;
  2419.      tree add_args;
  2420. {
  2421.   tree method_decl;
  2422.  
  2423.   /* if no type is specified, default to "id" */
  2424.   if (ret_type == NULLT)
  2425.     ret_type = build_tree_list (build_tree_list (NULLT, objc_object_reference),
  2426.                 build1 (INDIRECT_REF, NULLT, NULLT));
  2427.  
  2428.   method_decl = make_node (code);
  2429.   TREE_TYPE (method_decl) = ret_type;
  2430.  
  2431.   /*
  2432.    *  if we have a keyword selector, create an identifier_node that
  2433.    *  represents the full selector name (`:' included)...
  2434.    */
  2435.   if (TREE_CODE (selector) == KEYWORD_DECL)
  2436.     {
  2437.       METHOD_SEL_NAME (method_decl) = build_keyword_selector (selector);
  2438.       METHOD_SEL_ARGS (method_decl) = selector;
  2439.       METHOD_ADD_ARGS (method_decl) = add_args;
  2440.     }
  2441.   else
  2442.     {
  2443.       METHOD_SEL_NAME (method_decl) = selector;
  2444.       METHOD_SEL_ARGS (method_decl) = NULLT;
  2445.       METHOD_ADD_ARGS (method_decl) = NULLT;
  2446.     }
  2447.  
  2448.   return method_decl;
  2449. }
  2450.  
  2451. #define METHOD_DEF 0
  2452. #define METHOD_REF 1
  2453. /* Used by `build_message_expr' and `comp_method_types'.
  2454.    Return an argument list for method METH.
  2455.    CONTEXT is either METHOD_DEF or METHOD_REF,
  2456.     saying whether we are trying to define a method or call one.
  2457.    SUPERFLAG says this is for a send to super;
  2458.     this makes a difference for the NeXT calling sequence
  2459.     in which the lookup and the method call are done together.  */
  2460.  
  2461. static tree
  2462. get_arg_type_list (meth, context, superflag)
  2463.      tree meth;
  2464.      int context;
  2465.      int superflag;
  2466. {
  2467.   tree arglist, akey;
  2468.  
  2469. #ifdef NEXT_OBJC_RUNTIME
  2470.   /* receiver type */
  2471.   if (superflag)
  2472.     {
  2473.       arglist = build_tree_list (NULLT, super_type);
  2474.     }
  2475.   else
  2476. #endif
  2477.     {
  2478.       if (context == METHOD_DEF)
  2479.     arglist = build_tree_list (NULLT, TREE_TYPE (self_decl));
  2480.       else
  2481.     arglist = build_tree_list (NULLT, id_type);
  2482.     }
  2483.  
  2484.   /* selector type - will eventually change to `int' */
  2485.   chainon (arglist, build_tree_list (NULLT, selector_type));
  2486.  
  2487.   /* build a list of argument types */
  2488.   for (akey = METHOD_SEL_ARGS (meth); akey; akey = TREE_CHAIN (akey))
  2489.     {
  2490.       tree arg_decl = groktypename_in_parm_context (TREE_TYPE (akey));
  2491.       chainon (arglist, build_tree_list (NULLT, TREE_TYPE (arg_decl)));
  2492.     }
  2493.  
  2494.   if (METHOD_ADD_ARGS (meth) == (tree)1)
  2495.     /*
  2496.      * we have a `, ...' immediately following the selector,
  2497.      * finalize the arglist...simulate get_parm_info (0)
  2498.      */
  2499.     ;
  2500.   else if (METHOD_ADD_ARGS (meth))
  2501.     {
  2502.       /* we have a variable length selector */
  2503.       tree add_arg_list = TREE_CHAIN (METHOD_ADD_ARGS (meth));
  2504.       chainon (arglist, add_arg_list);
  2505.     }
  2506.   else                /* finalize the arglist...simulate get_parm_info (1) */
  2507.     chainon (arglist, build_tree_list (NULLT, void_type_node));
  2508.  
  2509.   return arglist;
  2510. }
  2511.  
  2512. static tree
  2513. check_duplicates (hsh)
  2514.      hash hsh;
  2515. {
  2516.   tree meth = NULLT;
  2517.  
  2518.   if (hsh)
  2519.     {
  2520.       meth = hsh->key;
  2521.  
  2522.       if (hsh->list)
  2523.         {
  2524.       /* we have two methods with the same name and different types */
  2525.       attr loop;
  2526.       char type;
  2527.  
  2528.       type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL) ? '-' : '+';
  2529.  
  2530.       warning ("multiple declarations for method `%s'",
  2531.            IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
  2532.  
  2533.       warn_with_method ("using", type, meth);
  2534.       for (loop = hsh->list; loop; loop = loop->next)
  2535.         warn_with_method ("also found", type, loop->value);
  2536.         }
  2537.     }
  2538.   return meth;
  2539. }
  2540.  
  2541. static tree
  2542. receiver_is_class_object (receiver)
  2543.       tree receiver;
  2544. {
  2545.   /* the receiver is a function call that returns an id...
  2546.    * ...check if it is a call to objc_getClass, if so, give it
  2547.    * special treatment.
  2548.    */
  2549.   tree exp = TREE_OPERAND (receiver, 0);
  2550.  
  2551.   if (exp != 0 && (TREE_CODE (exp) == ADDR_EXPR))
  2552.     {
  2553.       exp = TREE_OPERAND (exp, 0);
  2554.       if (exp != 0
  2555.       && TREE_CODE (exp) == FUNCTION_DECL && exp == objc_getClass_decl)
  2556.     {
  2557.       /* we have a call to objc_getClass! */
  2558.       tree arg = TREE_OPERAND (receiver, 1);
  2559.  
  2560.       if (arg != 0
  2561.           && TREE_CODE (arg) == TREE_LIST
  2562.           && (arg = TREE_VALUE (arg))
  2563.           && TREE_CODE (arg) == NOP_EXPR
  2564.           && (arg = TREE_OPERAND (arg, 0))
  2565.           && TREE_CODE (arg) == ADDR_EXPR
  2566.           && (arg = TREE_OPERAND (arg, 0))
  2567.           && TREE_CODE (arg) == STRING_CST)
  2568.         /* finally, we have the class name */
  2569.         return get_identifier (TREE_STRING_POINTER (arg));
  2570.     }
  2571.     }
  2572.   return 0;
  2573. }
  2574.  
  2575. /* If we are currently building a message expr, this holds
  2576.    the identifier of the selector of the message.  This is
  2577.    used when printing warnings about argument mismatches. */
  2578.  
  2579. static tree building_objc_message_expr = 0;
  2580.  
  2581. tree
  2582. maybe_building_objc_message_expr ()
  2583. {
  2584.   return building_objc_message_expr;
  2585. }
  2586.  
  2587. /* Construct an expression for sending a message.
  2588.    MESS has the object to send to in TREE_PURPOSE
  2589.    and the argument list (including selector) in TREE_VALUE.  */
  2590.  
  2591. tree
  2592. build_message_expr (mess)
  2593.      tree mess;
  2594. {
  2595.   tree receiver = TREE_PURPOSE (mess);
  2596.   tree selector, self_object;
  2597.   tree rtype, sel_name;
  2598.   tree args = TREE_VALUE (mess);
  2599.   tree method_params = NULLT;
  2600.   tree method_prototype = NULLT;
  2601.   int selTransTbl_index;
  2602.   tree retval;
  2603.   int statically_typed = 0, statically_allocated = 0;
  2604.   tree class_ident = 0;
  2605.  
  2606.   /* 1 if this is sending to the superclass.  */
  2607.   int super;
  2608.  
  2609.   if (!doing_objc_thang)
  2610.     fatal ("Objective-C text in C source file");
  2611.  
  2612.   if (TREE_CODE (receiver) == ERROR_MARK)
  2613.     return error_mark_node;
  2614.  
  2615.   /* determine receiver type */
  2616.   rtype = TREE_TYPE (receiver);
  2617.   super = (TREE_TYPE (receiver) == super_type);
  2618.  
  2619.   if (! super)
  2620.     {
  2621.       if (TREE_STATIC_TEMPLATE (rtype))
  2622.     statically_allocated = 1;
  2623.       else if (TREE_CODE (rtype) == POINTER_TYPE
  2624.            && TREE_STATIC_TEMPLATE (TREE_TYPE (rtype)))
  2625.     statically_typed = 1;
  2626.       /* classfix -smn */
  2627.       else if (TREE_CODE (receiver) == CALL_EXPR && rtype == id_type
  2628.            && (class_ident = receiver_is_class_object (receiver)))
  2629.     ;
  2630.       else if (rtype != id_type && rtype != class_type)
  2631.     {
  2632.       bzero (errbuf, BUFSIZE);
  2633.       warning ("invalid receiver type `%s'", gen_declaration (rtype, errbuf));
  2634.     }
  2635.       if (statically_allocated)
  2636.     receiver = build_unary_op (ADDR_EXPR, receiver, 0);
  2637.  
  2638.       self_object = receiver;
  2639.     }
  2640.   else
  2641.     /* If sending to `super', use current self as the object.  */
  2642.     self_object = self_decl;
  2643.  
  2644.   /* Obtain the full selector name.  */
  2645.  
  2646.   if (TREE_CODE (args) == IDENTIFIER_NODE)
  2647.     /* a unary selector */
  2648.     sel_name = args;
  2649.   else if (TREE_CODE (args) == TREE_LIST)
  2650.     sel_name = build_keyword_selector (args);
  2651.  
  2652.   selTransTbl_index = add_selector_reference (sel_name);
  2653.  
  2654.   /* Build the parameters list for looking up the method.
  2655.      These are the object itself and the selector.  */
  2656.   
  2657. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  2658.   selector = build_selector_reference (selTransTbl_index);
  2659. #else
  2660.   selector = build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
  2661.                   build_int_2 (selTransTbl_index, 0));
  2662. #endif
  2663.  
  2664.   /* Build the parameter list to give to the method.  */
  2665.  
  2666.   method_params = NULLT;
  2667.   if (TREE_CODE (args) == TREE_LIST)
  2668.     {
  2669.       tree chain = args, prev = NULLT;
  2670.  
  2671.       /* We have a keyword selector--check for comma expressions.  */
  2672.       while (chain)
  2673.     {
  2674.       tree element = TREE_VALUE (chain);
  2675.  
  2676.       /* We have a comma expression, must collapse...  */
  2677.       if (TREE_CODE (element) == TREE_LIST)
  2678.         {
  2679.           if (prev)
  2680.         TREE_CHAIN (prev) = element;
  2681.           else
  2682.         args = element;
  2683.         }
  2684.       prev = chain;
  2685.       chain = TREE_CHAIN (chain);
  2686.         }
  2687.       method_params = args;
  2688.     }
  2689.  
  2690.   /* Determine operation return type.  */
  2691.  
  2692.   if (rtype == super_type)
  2693.     {
  2694.       tree iface;
  2695.  
  2696.       if (CLASS_SUPER_NAME (implementation_template))
  2697.     {
  2698.       iface = lookup_interface (CLASS_SUPER_NAME (implementation_template));
  2699.     
  2700.       if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
  2701.         method_prototype = lookup_instance_method_static (iface, sel_name);
  2702.       else
  2703.         method_prototype = lookup_class_method_static (iface, sel_name);
  2704.     
  2705.       if (iface && !method_prototype)
  2706.         warning ("`%s' does not respond to `%s'",
  2707.              IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)),
  2708.              IDENTIFIER_POINTER (sel_name));
  2709.     }
  2710.       else
  2711.     {
  2712.       error ("no super class declared in interface for `%s'",
  2713.          IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
  2714.       return error_mark_node;
  2715.     }
  2716.  
  2717.     }
  2718.   else if (statically_allocated)
  2719.     {
  2720.       tree iface = lookup_interface (TYPE_NAME (rtype));
  2721.  
  2722.       if (iface && !(method_prototype = lookup_instance_method_static (iface, sel_name)))
  2723.     warning ("`%s' does not respond to `%s'",
  2724.          IDENTIFIER_POINTER (TYPE_NAME (rtype)),
  2725.          IDENTIFIER_POINTER (sel_name));
  2726.     }
  2727.   else if (statically_typed)
  2728.     {
  2729.       tree ctype = TREE_TYPE (rtype);
  2730.  
  2731.       /* `self' is now statically_typed...all methods should be visible
  2732.        * within the context of the implementation...
  2733.        */
  2734.       if (implementation_context
  2735.       && CLASS_NAME (implementation_context) == TYPE_NAME (ctype))
  2736.     {
  2737.       method_prototype = lookup_instance_method_static (implementation_template, sel_name);
  2738.  
  2739.       if (!method_prototype && implementation_template != implementation_context)
  2740.         /* the method is not published in the interface...check locally */
  2741.         method_prototype = lookup_method (CLASS_NST_METHODS (implementation_context),
  2742.                   sel_name);
  2743.     }
  2744.       else
  2745.     {
  2746.       tree iface;
  2747.  
  2748.       if (iface = lookup_interface (TYPE_NAME (ctype)))
  2749.         method_prototype = lookup_instance_method_static (iface, sel_name);
  2750.     }
  2751.  
  2752.       if (!method_prototype)
  2753.         warning ("`%s' does not respond to `%s'",
  2754.          IDENTIFIER_POINTER (TYPE_NAME (ctype)),
  2755.          IDENTIFIER_POINTER (sel_name));
  2756.     }
  2757.   else if (class_ident)
  2758.     {
  2759.       if (implementation_context
  2760.       && CLASS_NAME (implementation_context) == class_ident)
  2761.     {
  2762.       method_prototype
  2763.         = lookup_class_method_static (implementation_template, sel_name);
  2764.     
  2765.       if (!method_prototype
  2766.           && implementation_template != implementation_context)
  2767.         /* the method is not published in the interface...check locally */
  2768.         method_prototype
  2769.           = lookup_method (CLASS_CLS_METHODS (implementation_context),
  2770.                    sel_name);
  2771.     }
  2772.       else
  2773.     {
  2774.       tree iface;
  2775.     
  2776.       if (iface = lookup_interface (class_ident))
  2777.         method_prototype = lookup_class_method_static (iface, sel_name);
  2778.     }
  2779.   
  2780.       if (!method_prototype)
  2781.     {
  2782.       warning ("cannot find class (factory) method.");
  2783.       warning ("return type for `%s' defaults to id",
  2784.            IDENTIFIER_POINTER (sel_name));
  2785.     }
  2786.     }
  2787.   else
  2788.     {
  2789.       hash hsh;
  2790.  
  2791.       /* we think we have an instance...loophole: extern id Object; */
  2792.       hsh = hash_lookup (nst_method_hash_list, sel_name);
  2793.       if (!hsh)
  2794.     /* for various loopholes...like sending messages to self in a
  2795.        factory context... */
  2796.     hsh = hash_lookup (cls_method_hash_list, sel_name);
  2797.  
  2798.       method_prototype = check_duplicates (hsh);
  2799.       if (!method_prototype)
  2800.     {
  2801.       warning ("cannot find method.");
  2802.       warning ("return type for `%s' defaults to id",
  2803.            IDENTIFIER_POINTER (sel_name));
  2804.     }
  2805.     }
  2806.  
  2807.   /* Save the selector name for printing error messages.  */
  2808.   building_objc_message_expr = sel_name;
  2809.  
  2810.   retval = build_objc_method_call (super, method_prototype,
  2811.                    receiver, self_object,
  2812.                    selector, method_params);
  2813.  
  2814.   building_objc_message_expr = 0;
  2815.  
  2816.   return retval;
  2817. }
  2818.  
  2819. /* Build a tree expression to send OBJECT the operation SELECTOR,
  2820.    looking up the method on object LOOKUP_OBJECT (often same as OBJECT),
  2821.    assuming the method has prototype METHOD_PROTOTYPE.
  2822.    (That is an INSTANCE_METHOD_DECL or CLASS_METHOD_DECL.)
  2823.    Use METHOD_PARAMS as list of args to pass to the method.
  2824.    If SUPER_FLAG is nonzero, we look up the superclass's method.  */
  2825.  
  2826. static tree
  2827. build_objc_method_call (super_flag, method_prototype, lookup_object, object,
  2828.             selector, method_params)
  2829.      int super_flag;
  2830.      tree method_prototype, lookup_object, object, selector, method_params;
  2831. {
  2832.   tree sender = (super_flag ? _msgSuper_decl : _msg_decl);
  2833.  
  2834. #ifdef NEXT_OBJC_RUNTIME
  2835.   if (!method_prototype)
  2836.     {
  2837.       method_params = tree_cons (NULLT, lookup_object,
  2838.                  tree_cons (NULLT, selector, method_params));
  2839.       return build_function_call (sender, method_params);
  2840.     }
  2841.   else
  2842.     {
  2843.       /* This is a real kludge, but it is used only for the Next.
  2844.      Clobber the data type of SENDER temporarily to accept
  2845.      all the arguments for this operation, and to return
  2846.      whatever this operation returns.  */
  2847.       tree arglist = NULLT;
  2848.       tree retval;
  2849.  
  2850.       /* Save the proper contents of SENDER's data type.  */
  2851.       tree savarg = TYPE_ARG_TYPES (TREE_TYPE (sender));
  2852.       tree savret = TREE_TYPE (TREE_TYPE (sender));
  2853.  
  2854.       /* Install this method's argument types.  */
  2855.       arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
  2856.       TYPE_ARG_TYPES (TREE_TYPE (sender)) = arglist;
  2857.  
  2858.       /* Install this method's return type.  */
  2859.       TREE_TYPE (TREE_TYPE (sender))
  2860.     = groktypename (TREE_TYPE (method_prototype));
  2861.  
  2862.       /* Call SENDER with all the parameters.
  2863.      This will do type checking using the arg types for this method.  */
  2864.       method_params = tree_cons (NULLT, lookup_object,
  2865.                  tree_cons (NULLT, selector, method_params));
  2866.       retval = build_function_call (sender, method_params);
  2867.  
  2868.       /* Restore SENDER's return/argument types.  */
  2869.       TYPE_ARG_TYPES (TREE_TYPE (sender)) = savarg;
  2870.       TREE_TYPE (TREE_TYPE (sender)) = savret;
  2871.       return retval;
  2872.     }
  2873. #else /* not NEXT_OBJC_RUNTIME */
  2874.   /* This is the portable way.
  2875.      First call the lookup function to get a pointer to the method, 
  2876.      then cast the pointer, then call it with the method arguments.  */
  2877.   tree method;
  2878.  
  2879.   /* Avoid trouble since we may evaluate each of these twice.  */
  2880.   object = save_expr (object);
  2881.   selector = save_expr (selector);
  2882.  
  2883.   method
  2884.     = build_function_call (sender,
  2885.                tree_cons (NULLT, lookup_object,
  2886.                       tree_cons (NULLT, selector, NULLT)));
  2887.  
  2888.   /* If we have a method prototype, construct the data type this method needs,
  2889.      and cast what we got from SENDER into a pointer to that type.  */
  2890.   if (method_prototype)
  2891.     {
  2892.       tree arglist = get_arg_type_list (method_prototype, METHOD_REF, super_flag);
  2893.       tree valtype = groktypename (TREE_TYPE (method_prototype));
  2894.       tree fake_function_type = build_function_type (valtype, arglist);
  2895.       TREE_TYPE (method) = build_pointer_type (fake_function_type);
  2896.     }
  2897.   else
  2898.     {
  2899.       TREE_TYPE (method)
  2900.     = build_pointer_type (build_function_type (ptr_type_node, NULLT));
  2901.     }
  2902.   /* Pass the object to the method.  */
  2903.   return build_function_call (method,
  2904.                   tree_cons (NULLT, object,
  2905.                      tree_cons (NULLT, selector,
  2906.                             method_params)));
  2907. #endif /* not NEXT_OBJC_RUNTIME */
  2908. }
  2909.  
  2910. tree
  2911. build_selector_expr (selnamelist)
  2912.      tree selnamelist;
  2913. {
  2914.   tree selname;
  2915.   int selTransTbl_index;
  2916.  
  2917.   if (!doing_objc_thang)
  2918.     fatal ("Objective-C text in C source file");
  2919.  
  2920.   /* obtain the full selector name */
  2921.   if (TREE_CODE (selnamelist) == IDENTIFIER_NODE)
  2922.     /* a unary selector */
  2923.     selname = selnamelist;
  2924.   else if (TREE_CODE (selnamelist) == TREE_LIST)
  2925.     selname = build_keyword_selector (selnamelist);
  2926.  
  2927.   selTransTbl_index = add_selector_reference (selname);
  2928.  
  2929. #ifndef OBJC_SELECTORS_WITHOUT_LABELS
  2930.   return build_selector_reference (selTransTbl_index);
  2931. #else
  2932.   /* synthesize a reference into the selector translation table */
  2933.   return build_array_ref (_OBJC_SELECTOR_REFERENCES_decl,
  2934.               build_int_2 (selTransTbl_index, 0));
  2935. #endif
  2936. }
  2937.  
  2938. tree
  2939. build_encode_expr (type)
  2940.      tree type;
  2941. {
  2942.   tree result;
  2943.   char *string;
  2944.  
  2945.   if (!doing_objc_thang)
  2946.     fatal ("Objective-C text in C source file");
  2947.  
  2948.   encode_type (type, OBJC_ENCODE_INLINE_DEFS);
  2949.   string = obstack_finish (&util_obstack);
  2950.  
  2951.   /* synthesize a string that represents the encoded struct/union */
  2952.   result = my_build_string (strlen (string) + 1, string);
  2953.   obstack_free (&util_obstack, util_firstobj);
  2954.   return result;
  2955. }
  2956.  
  2957. tree
  2958. build_ivar_reference (id)
  2959.      tree id;
  2960. {
  2961.   if (TREE_CODE (method_context) == CLASS_METHOD_DECL)
  2962.     TREE_TYPE (self_decl) = instance_type; /* cast */
  2963.  
  2964.   return build_component_ref (build_indirect_ref (self_decl, "->"), id);
  2965. }
  2966.  
  2967. #define HASH_ALLOC_LIST_SIZE    170
  2968. #define ATTR_ALLOC_LIST_SIZE    170
  2969. #define SIZEHASHTABLE         257
  2970. #define HASHFUNCTION(key)    ((int)key >> 2)     /* divide by 4 */
  2971.  
  2972. static void
  2973. hash_init ()
  2974. {
  2975.   nst_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
  2976.   cls_method_hash_list = (hash *)xmalloc (SIZEHASHTABLE * sizeof (hash));
  2977.  
  2978.   if (!nst_method_hash_list || !cls_method_hash_list)
  2979.     perror ("unable to allocate space in objc-tree.c");
  2980.   else
  2981.     {
  2982.       int i;
  2983.  
  2984.       for (i = 0; i < SIZEHASHTABLE; i++)
  2985.     {
  2986.       nst_method_hash_list[i] = 0;
  2987.       cls_method_hash_list[i] = 0;
  2988.     }
  2989.     }
  2990. }
  2991.  
  2992. static void
  2993. hash_enter (hashlist, method)
  2994.      hash *hashlist;
  2995.      tree method;
  2996. {
  2997.   static hash     hash_alloc_list = 0;
  2998.   static int    hash_alloc_index = 0;
  2999.   hash obj;
  3000.   int slot = HASHFUNCTION (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
  3001.  
  3002.   if (!hash_alloc_list || hash_alloc_index >= HASH_ALLOC_LIST_SIZE)
  3003.     {
  3004.       hash_alloc_index = 0;
  3005.       hash_alloc_list = (hash)xmalloc (sizeof (struct hashedEntry) *
  3006.                       HASH_ALLOC_LIST_SIZE);
  3007.       if (!hash_alloc_list)
  3008.     perror ("unable to allocate in objc-tree.c");
  3009.     }
  3010.   obj = &hash_alloc_list[hash_alloc_index++];
  3011.   obj->list = 0;
  3012.   obj->next = hashlist[slot];
  3013.   obj->key = method;
  3014.  
  3015.   hashlist[slot] = obj;        /* append to front */
  3016. }
  3017.  
  3018. static hash
  3019. hash_lookup (hashlist, sel_name)
  3020.      hash *hashlist;
  3021.      tree sel_name;
  3022. {
  3023.   hash target;
  3024.  
  3025.   target = hashlist[HASHFUNCTION (sel_name) % SIZEHASHTABLE];
  3026.  
  3027.   while (target)
  3028.     {
  3029.       if (sel_name == METHOD_SEL_NAME (target->key))
  3030.     return target;
  3031.  
  3032.       target = target->next;
  3033.     }
  3034.   return 0;
  3035. }
  3036.  
  3037. static void
  3038. hash_add_attr (entry, value)
  3039.      hash entry;
  3040.      tree value;
  3041. {
  3042.   static attr     attr_alloc_list = 0;
  3043.   static int    attr_alloc_index = 0;
  3044.   attr obj;
  3045.  
  3046.   if (!attr_alloc_list || attr_alloc_index >= ATTR_ALLOC_LIST_SIZE)
  3047.     {
  3048.       attr_alloc_index = 0;
  3049.       attr_alloc_list = (attr)xmalloc (sizeof (struct hashedAttribute) *
  3050.                       ATTR_ALLOC_LIST_SIZE);
  3051.       if (!attr_alloc_list)
  3052.     perror ("unable to allocate in objc-tree.c");
  3053.     }
  3054.   obj = &attr_alloc_list[attr_alloc_index++];
  3055.   obj->next = entry->list;
  3056.   obj->value = value;
  3057.  
  3058.   entry->list = obj;        /* append to front */
  3059. }
  3060.  
  3061. static tree
  3062. lookup_method (mchain, method)
  3063.      tree mchain;
  3064.      tree method;
  3065. {
  3066.   tree key;
  3067.  
  3068.   if (TREE_CODE (method) == IDENTIFIER_NODE)
  3069.     key = method;
  3070.   else
  3071.     key = METHOD_SEL_NAME (method);
  3072.  
  3073.   while (mchain)
  3074.     {
  3075.       if (METHOD_SEL_NAME (mchain) == key)
  3076.     return mchain;
  3077.       mchain = TREE_CHAIN (mchain);
  3078.     }
  3079.   return NULLT;
  3080. }
  3081.  
  3082. static tree
  3083. lookup_instance_method_static (interface, ident)
  3084.      tree interface;
  3085.      tree ident;
  3086. {
  3087.   tree inter = interface;
  3088.   tree chain = CLASS_NST_METHODS (inter);
  3089.   tree meth = NULLT;
  3090.  
  3091.   do
  3092.     {
  3093.       if (meth = lookup_method (chain, ident))
  3094.     return meth;
  3095.  
  3096.       if (CLASS_CATEGORY_LIST (inter))
  3097.     {
  3098.       tree category = CLASS_CATEGORY_LIST (inter);
  3099.       chain = CLASS_NST_METHODS (category);
  3100.     
  3101.       do 
  3102.         {
  3103.           if (meth = lookup_method (chain, ident))
  3104.         return meth;
  3105.       
  3106.           if (category = CLASS_CATEGORY_LIST (category))
  3107.         chain = CLASS_NST_METHODS (category);
  3108.         }
  3109.       while (category);
  3110.     }
  3111.  
  3112.       if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
  3113.     chain = CLASS_NST_METHODS (inter);
  3114.     }
  3115.   while (inter);
  3116.  
  3117.   return meth;
  3118. }
  3119.  
  3120. static tree
  3121. lookup_class_method_static (interface, ident)
  3122.      tree interface;
  3123.      tree ident;
  3124. {
  3125.   tree inter = interface;
  3126.   tree chain = CLASS_CLS_METHODS (inter);
  3127.   tree meth = NULLT;
  3128.  
  3129.   do
  3130.     {
  3131.       if (meth = lookup_method (chain, ident))
  3132.     return meth;
  3133.  
  3134.       if (CLASS_CATEGORY_LIST (inter))
  3135.     {
  3136.       tree category = CLASS_CATEGORY_LIST (inter);
  3137.       chain = CLASS_CLS_METHODS (category);
  3138.     
  3139.       do 
  3140.         {
  3141.           if (meth = lookup_method (chain, ident))
  3142.         return meth;
  3143.       
  3144.           if (category = CLASS_CATEGORY_LIST (category))
  3145.         chain = CLASS_CLS_METHODS (category);
  3146.         }
  3147.       while (category);
  3148.     }
  3149.  
  3150.       if (inter = lookup_interface (CLASS_SUPER_NAME (inter)))
  3151.     chain = CLASS_CLS_METHODS (inter);
  3152.     }
  3153.   while (inter);
  3154.  
  3155.   return meth;
  3156. }
  3157.  
  3158. tree
  3159. add_class_method (class, method)
  3160.      tree class;
  3161.      tree method;
  3162. {
  3163.   tree mth;
  3164.   hash hsh;
  3165.  
  3166.   if (!(mth = lookup_method (CLASS_CLS_METHODS (class), method)))
  3167.     {
  3168.       /* put method on list in reverse order */
  3169.       TREE_CHAIN (method) = CLASS_CLS_METHODS (class);
  3170.       CLASS_CLS_METHODS (class) = method;
  3171.     }
  3172.   else
  3173.     {
  3174.       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
  3175.     error ("duplicate definition of class method `%s'.",
  3176.            IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
  3177.       else
  3178.         {
  3179.       /* check types, if different complain */
  3180.       if (!comp_proto_with_proto (method, mth))
  3181.         error ("duplicate declaration of class method `%s'.",
  3182.            IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
  3183.         }
  3184.     }
  3185.  
  3186.   if (!(hsh = hash_lookup (cls_method_hash_list, METHOD_SEL_NAME (method))))
  3187.     {
  3188.       /* install on a global chain */
  3189.       hash_enter (cls_method_hash_list, method);
  3190.     }
  3191.   else
  3192.     {
  3193.       /* check types, if different add to a list */
  3194.       if (!comp_proto_with_proto (method, hsh->key))
  3195.         hash_add_attr (hsh, method);
  3196.     }
  3197.   return method;
  3198. }
  3199.  
  3200. tree
  3201. add_instance_method (class, method)
  3202.      tree class;
  3203.      tree method;
  3204. {
  3205.   tree mth;
  3206.   hash hsh;
  3207.  
  3208.   if (!(mth = lookup_method (CLASS_NST_METHODS (class), method)))
  3209.     {
  3210.       /* put method on list in reverse order */
  3211.       TREE_CHAIN (method) = CLASS_NST_METHODS (class);
  3212.       CLASS_NST_METHODS (class) = method;
  3213.     }
  3214.   else
  3215.     {
  3216.       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
  3217.     error ("duplicate definition of instance method `%s'.",
  3218.            IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
  3219.       else
  3220.         {
  3221.       /* check types, if different complain */
  3222.       if (!comp_proto_with_proto (method, mth))
  3223.         error ("duplicate declaration of instance method `%s'.",
  3224.            IDENTIFIER_POINTER (METHOD_SEL_NAME (mth)));
  3225.         }
  3226.     }
  3227.  
  3228.   if (!(hsh = hash_lookup (nst_method_hash_list, METHOD_SEL_NAME (method))))
  3229.     {
  3230.       /* install on a global chain */
  3231.       hash_enter (nst_method_hash_list, method);
  3232.     }
  3233.   else
  3234.     {
  3235.       /* check types, if different add to a list */
  3236.       if (!comp_proto_with_proto (method, hsh->key))
  3237.         hash_add_attr (hsh, method);
  3238.     }
  3239.   return method;
  3240. }
  3241.  
  3242. static tree
  3243. add_class (class)
  3244.      tree class;
  3245. {
  3246.   /* put interfaces on list in reverse order */
  3247.   TREE_CHAIN (class) = interface_chain;
  3248.   interface_chain = class;
  3249.   return interface_chain;
  3250. }
  3251.  
  3252. static void
  3253. add_category (class, category)
  3254.       tree class;
  3255.       tree category;
  3256. {
  3257.   /* put categories on list in reverse order */
  3258.   CLASS_CATEGORY_LIST (category) = CLASS_CATEGORY_LIST (class);
  3259.   CLASS_CATEGORY_LIST (class) = category;
  3260. }
  3261.  
  3262. /* called after parsing each instance variable declaration. Necessary to
  3263.  * preserve typedefs and implement public/private...
  3264.  */
  3265. tree
  3266. add_instance_variable (class, public, declarator, declspecs, width)
  3267.      tree class;
  3268.      int public;
  3269.      tree declarator;
  3270.      tree declspecs;
  3271.      tree width;
  3272. {
  3273.   tree field_decl, raw_decl;
  3274.  
  3275.   raw_decl = build_tree_list (declspecs    /*purpose*/, declarator/*value*/);
  3276.  
  3277.   if (CLASS_RAW_IVARS (class))
  3278.     chainon (CLASS_RAW_IVARS (class), raw_decl);
  3279.   else
  3280.     CLASS_RAW_IVARS (class) = raw_decl;
  3281.  
  3282.   field_decl = grokfield (input_filename, lineno,
  3283.               declarator, declspecs, width);
  3284.  
  3285.   /* overload the public attribute, it is not used for FIELD_DECL's */
  3286.   if (public)
  3287.     TREE_PUBLIC (field_decl) = 1;
  3288.  
  3289.   if (CLASS_IVARS (class))
  3290.     chainon (CLASS_IVARS (class), field_decl);
  3291.   else
  3292.     CLASS_IVARS (class) = field_decl;
  3293.  
  3294.   return class;
  3295. }
  3296.  
  3297. tree
  3298. is_ivar (decl_chain, ident)
  3299.      tree decl_chain;
  3300.      tree ident;
  3301. {
  3302.   for ( ; decl_chain; decl_chain = TREE_CHAIN (decl_chain))
  3303.     if (DECL_NAME (decl_chain) == ident)
  3304.       return decl_chain;
  3305.   return NULL_TREE;
  3306. }
  3307.  
  3308. /* we have an instance variable reference, check to see if it is public...*/
  3309.  
  3310. int
  3311. is_public (expr, identifier)
  3312.      tree expr;
  3313.      tree identifier;
  3314. {
  3315.   tree basetype = TREE_TYPE (expr);
  3316.   enum tree_code code = TREE_CODE (basetype);
  3317.   tree decl;
  3318.  
  3319.   if (code == RECORD_TYPE)
  3320.     {
  3321.       if (TREE_STATIC_TEMPLATE (basetype))
  3322.     {
  3323.       if (decl = is_ivar (TYPE_FIELDS (basetype), identifier))
  3324.         {
  3325.           /* important difference between the Stepstone translator:
  3326.          
  3327.          all instance variables should be public within the context
  3328.          of the implementation...
  3329.          */
  3330.           if (implementation_context)
  3331.         {
  3332.           if ((TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE
  3333.                && CLASS_NAME (implementation_context) == TYPE_NAME (basetype))
  3334.               || (TREE_CODE (implementation_context) == CATEGORY_TYPE
  3335.               && CLASS_NAME (implementation_context) == TYPE_NAME (basetype)))
  3336.             return 1;
  3337.         }
  3338.  
  3339.           if (TREE_PUBLIC (decl))
  3340.         return 1;
  3341.  
  3342.           error ("instance variable `%s' is declared private",
  3343.              IDENTIFIER_POINTER (identifier));
  3344.           return 0;
  3345.         }
  3346.     }
  3347.       else if (implementation_context && (basetype == objc_object_reference))
  3348.     {
  3349.       TREE_TYPE (expr) = _PRIVATE_record;
  3350.       if (extra_warnings)
  3351.         {
  3352.           warning ("static access to object of type `id'");
  3353.           warning ("please change to type `%s *'",
  3354.                IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
  3355.         }
  3356.     }
  3357.     }
  3358.   return 1;
  3359. }
  3360.  
  3361. /* implement @defs (<classname>) within struct bodies. */
  3362.  
  3363. tree
  3364. get_class_ivars (interface)
  3365.      tree interface;
  3366. {
  3367.   if (!doing_objc_thang)
  3368.     fatal ("Objective-C text in C source file");
  3369.  
  3370.   return build_ivar_chain (interface);
  3371. }
  3372.  
  3373. tree
  3374. get_class_reference (interface)
  3375.      tree interface;
  3376. {
  3377.   tree params;
  3378.  
  3379.   add_class_reference (CLASS_NAME (interface));
  3380.  
  3381.   params = build_tree_list (NULLT,
  3382.                 my_build_string (IDENTIFIER_LENGTH (CLASS_NAME (interface)) + 1,
  3383.                          IDENTIFIER_POINTER (CLASS_NAME (interface))));
  3384.  
  3385.   return build_function_call (objc_getClass_decl, params);
  3386. }
  3387.  
  3388. /* make sure all entries in "chain" are also in "list" */
  3389.  
  3390. static void
  3391. check_methods (chain, list, mtype)
  3392.      tree chain;
  3393.      tree list;
  3394.      int mtype;
  3395. {
  3396.   int first = 1;
  3397.  
  3398.   while (chain)
  3399.     {
  3400.       if (!lookup_method (list, chain))
  3401.     {
  3402.       if (first)
  3403.         {
  3404.           if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  3405.         warning ("incomplete implementation of class `%s'",
  3406.              IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
  3407.           else if (TREE_CODE (implementation_context) == CATEGORY_TYPE)
  3408.         warning ("incomplete implementation of category `%s'",
  3409.              IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
  3410.           first = 0;
  3411.         }
  3412.       warning ("method definition for `%c%s' not found",
  3413.            mtype, IDENTIFIER_POINTER (METHOD_SEL_NAME (chain)));
  3414.     }
  3415.       chain = TREE_CHAIN (chain);
  3416.     }
  3417. }
  3418.  
  3419. tree
  3420. start_class (code, class_name, super_name)
  3421.      enum tree_code code;
  3422.      tree class_name;
  3423.      tree super_name;
  3424. {
  3425.   tree class;
  3426.  
  3427.   if (!doing_objc_thang)
  3428.      fatal ("Objective-C text in C source file");
  3429.  
  3430.   class = make_node (code);
  3431.  
  3432.   CLASS_NAME (class) = class_name;
  3433.   CLASS_SUPER_NAME (class) = super_name;
  3434.   CLASS_CLS_METHODS (class) = NULL_TREE;
  3435.  
  3436.   if (code == IMPLEMENTATION_TYPE)
  3437.     {
  3438.       /* pre-build the following entities - for speed/convenience. */
  3439.       if (!self_id)
  3440.         self_id = get_identifier ("self");
  3441.       if (!_cmd_id)
  3442.         _cmd_id = get_identifier ("_cmd");
  3443.  
  3444.       if (!objc_super_template)
  3445.     objc_super_template = build_super_template ();
  3446.  
  3447.       method_slot = 0;        /* reset for multiple classes per file */
  3448.  
  3449.       implementation_context = class;
  3450.  
  3451.       /* lookup the interface for this implementation. */
  3452.  
  3453.       if (!(implementation_template = lookup_interface (class_name)))
  3454.         {
  3455.       warning ("Cannot find interface declaration for `%s'",
  3456.            IDENTIFIER_POINTER (class_name));
  3457.       add_class (implementation_template = implementation_context);
  3458.         }
  3459.  
  3460.       /* if a super class has been specified in the implementation,
  3461.      insure it conforms to the one specified in the interface */
  3462.  
  3463.       if (super_name
  3464.       && (super_name != CLASS_SUPER_NAME (implementation_template)))
  3465.         {
  3466.       error ("conflicting super class name `%s'",
  3467.          IDENTIFIER_POINTER (super_name));
  3468.       error ("previous declaration of `%s'",
  3469.          IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_template)));
  3470.         }
  3471.     }
  3472.   else if (code == INTERFACE_TYPE)
  3473.     {
  3474.       if (lookup_interface (class_name))
  3475.         warning ("duplicate interface declaration for class `%s'",
  3476.                  IDENTIFIER_POINTER (class_name));
  3477.       else
  3478.         add_class (class);
  3479.     }
  3480.   else if (code == PROTOCOL_TYPE)
  3481.     {
  3482.       tree class_category_is_assoc_with;
  3483.  
  3484.       /* for a category, class_name is really the name of the class that
  3485.      the following set of methods will be associated with...we must
  3486.      find the interface so that can derive the objects template */
  3487.  
  3488.       if (!(class_category_is_assoc_with = lookup_interface (class_name)))
  3489.     {
  3490.       error ("Cannot find interface declaration for `%s'",
  3491.          IDENTIFIER_POINTER (class_name));
  3492.       exit (1);
  3493.     }
  3494.       else
  3495.         add_category (class_category_is_assoc_with, class);
  3496.     }
  3497.   else if (code == CATEGORY_TYPE)
  3498.     {
  3499.       /* pre-build the following entities - for speed/convenience. */
  3500.       if (!self_id)
  3501.         self_id = get_identifier ("self");
  3502.       if (!_cmd_id)
  3503.         _cmd_id = get_identifier ("_cmd");
  3504.  
  3505.       if (!objc_super_template)
  3506.     objc_super_template = build_super_template ();
  3507.  
  3508.       method_slot = 0;        /* reset for multiple classes per file */
  3509.  
  3510.       implementation_context = class;
  3511.  
  3512.       /* for a category, class_name is really the name of the class that
  3513.      the following set of methods will be associated with...we must
  3514.      find the interface so that can derive the objects template */
  3515.  
  3516.       if (!(implementation_template = lookup_interface (class_name)))
  3517.         {
  3518.       error ("Cannot find interface declaration for `%s'",
  3519.          IDENTIFIER_POINTER (class_name));
  3520.       exit (1);
  3521.         }
  3522.     }
  3523.   return class;
  3524. }
  3525.  
  3526. tree
  3527. continue_class (class)
  3528.      tree class;
  3529. {
  3530.   if (TREE_CODE (class) == IMPLEMENTATION_TYPE
  3531.       || TREE_CODE (class) == CATEGORY_TYPE)
  3532.     {
  3533.       struct imp_entry *impEntry;
  3534.       tree ivar_context;
  3535.  
  3536.       /* check consistency of the instance variables. */
  3537.  
  3538.       if (CLASS_IVARS (class))
  3539.     check_ivars (implementation_template, class);
  3540.  
  3541.       /* code generation */
  3542.  
  3543.       ivar_context = build_private_template (implementation_template);
  3544.  
  3545.       if (!objc_class_template)
  3546.     build_class_template ();
  3547.  
  3548.       if (!(impEntry = (struct imp_entry *)xmalloc (sizeof (struct imp_entry))))
  3549.     perror ("unable to allocate in objc-tree.c");
  3550.  
  3551.       impEntry->next = imp_list;
  3552.       impEntry->imp_context = class;
  3553.       impEntry->imp_template = implementation_template;
  3554.  
  3555.       synth_forward_declarations ();
  3556.       impEntry->class_decl = _OBJC_CLASS_decl;
  3557.       impEntry->meta_decl = _OBJC_METACLASS_decl;
  3558.  
  3559.       /* append to front and increment count */
  3560.       imp_list = impEntry;
  3561.       if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
  3562.     imp_count++;
  3563.       else
  3564.     cat_count++;
  3565.  
  3566.       return ivar_context;
  3567.     }
  3568.   else if (TREE_CODE (class) == INTERFACE_TYPE)
  3569.     {
  3570.       tree record = xref_tag (RECORD_TYPE, CLASS_NAME (class));
  3571.  
  3572.       if (!TYPE_FIELDS (record))
  3573.     {
  3574.       finish_struct (record, build_ivar_chain (class));
  3575.       CLASS_STATIC_TEMPLATE (class) = record;
  3576.  
  3577.       /* mark this record as a class template - for static typing */
  3578.       TREE_STATIC_TEMPLATE (record) = 1;
  3579.     }
  3580.       return NULLT;
  3581.     }
  3582.   else
  3583.     return error_mark_node;
  3584. }
  3585.  
  3586. /*
  3587.  * this is called once we see the "@end" in an interface/implementation.
  3588.  */
  3589. void
  3590. finish_class (class)
  3591.      tree class;
  3592. {
  3593.   if (TREE_CODE (class) == IMPLEMENTATION_TYPE)
  3594.     {
  3595.       /* all code generation is done in finish_objc */
  3596.  
  3597.       if (implementation_template != implementation_context)
  3598.     {
  3599.       /* ensure that all method listed in the interface contain bodies! */
  3600.       check_methods (CLASS_CLS_METHODS (implementation_template),
  3601.              CLASS_CLS_METHODS (implementation_context), '+');
  3602.       check_methods (CLASS_NST_METHODS (implementation_template),
  3603.              CLASS_NST_METHODS (implementation_context), '-');
  3604.     }
  3605.     }
  3606.   else if (TREE_CODE (class) == CATEGORY_TYPE)
  3607.     {
  3608.       tree category = CLASS_CATEGORY_LIST (implementation_template);
  3609.   
  3610.       /* find the category interface from the class it is associated with */
  3611.       while (category)
  3612.     {
  3613.       if (CLASS_SUPER_NAME (class) == CLASS_SUPER_NAME (category))
  3614.         break;
  3615.       category = CLASS_CATEGORY_LIST (category);
  3616.     }
  3617.   
  3618.       if (category)
  3619.     {
  3620.       /* ensure that all method listed in the interface contain bodies! */
  3621.       check_methods (CLASS_CLS_METHODS (category),
  3622.              CLASS_CLS_METHODS (implementation_context), '+');
  3623.       check_methods (CLASS_NST_METHODS (category),
  3624.              CLASS_NST_METHODS (implementation_context), '-');
  3625.     }
  3626.     } 
  3627.   else if (TREE_CODE (class) == INTERFACE_TYPE)
  3628.     {
  3629.       tree decl_specs;
  3630.       char *string = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (class))) + 3);
  3631.  
  3632.       /* extern struct objc_object *_<my_name>; */
  3633.  
  3634.       sprintf (string, "_%s", IDENTIFIER_POINTER (CLASS_NAME (class)));
  3635.  
  3636.       decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_EXTERN]);
  3637.       decl_specs = tree_cons (NULLT, objc_object_reference, decl_specs);
  3638.       define_decl (build1 (INDIRECT_REF, NULLT, get_identifier (string)),
  3639.            decl_specs);
  3640.     }
  3641. }
  3642.  
  3643. /* "Encode" a data type into a string, whichg rows  in util_obstack.
  3644.    ??? What is the FORMAT?  Someone please document this!  */
  3645.  
  3646. /* Encode a pointer type.  */
  3647.  
  3648. static void
  3649. encode_pointer (type, format)
  3650.      tree type;
  3651.      int format;
  3652. {
  3653.   tree pointer_to = TREE_TYPE (type);
  3654.  
  3655.   if (TREE_CODE (pointer_to) == RECORD_TYPE)
  3656.     {
  3657.       if (TYPE_NAME (pointer_to)
  3658.       && TREE_CODE (TYPE_NAME (pointer_to)) == IDENTIFIER_NODE)
  3659.     {
  3660.       char *name = IDENTIFIER_POINTER (TYPE_NAME (pointer_to));
  3661.  
  3662.       if ((strcmp (name, TAG_OBJECT) == 0) /* '@' */
  3663.           || TREE_STATIC_TEMPLATE (pointer_to))
  3664.         {
  3665.           obstack_1grow (&util_obstack, '@');
  3666.           return;
  3667.         }
  3668.       else if (strcmp (name, TAG_CLASS) == 0) /* '#' */
  3669.         {
  3670.           obstack_1grow (&util_obstack, '#');
  3671.           return;
  3672.         }
  3673. #ifndef OBJC_INT_SELECTORS
  3674.       else if (strcmp (name, TAG_SELECTOR) == 0) /* ':' */
  3675.         {
  3676.           obstack_1grow (&util_obstack, ':');
  3677.           return;
  3678.         }
  3679. #endif /* OBJC_INT_SELECTORS */
  3680.     }
  3681.     }
  3682.   else if (TREE_CODE (pointer_to) == INTEGER_TYPE
  3683.        && TYPE_MODE (pointer_to) == QImode)
  3684.     {
  3685.       obstack_1grow (&util_obstack, '*');
  3686.       return;
  3687.     }
  3688.  
  3689.   /* we have a type that does not get special treatment... */
  3690.  
  3691.   /* NeXT extension */
  3692.   obstack_1grow (&util_obstack, '^');
  3693.   encode_type (pointer_to, format);
  3694. }
  3695.  
  3696. static void
  3697. encode_array (type, format)
  3698.      tree type;
  3699.      int format;
  3700. {
  3701.   tree anIntCst = TYPE_SIZE (type);
  3702.   tree array_of = TREE_TYPE (type);
  3703.   char buffer[40];
  3704.  
  3705.   /* An incomplete array is treated like a pointer.  */
  3706.   if (anIntCst == NULL)
  3707.     {
  3708.       /* split for obvious reasons.  North-Keys 30 Mar 1991 */
  3709.       encode_pointer (type, format);
  3710.       return;
  3711.     }
  3712.   
  3713.   sprintf (buffer, "[%d",
  3714.        TREE_INT_CST_LOW (anIntCst)
  3715.        / TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
  3716.   obstack_grow (&util_obstack, buffer, strlen (buffer));
  3717.   encode_type (array_of, format);
  3718.   obstack_1grow (&util_obstack, ']');
  3719.   return;
  3720. }
  3721.  
  3722. static void
  3723. encode_aggregate (type, format)
  3724.      tree type;
  3725.      int format;
  3726. {
  3727.   enum tree_code code = TREE_CODE (type);
  3728.  
  3729.   switch (code)
  3730.     {
  3731.     case RECORD_TYPE:
  3732.       {
  3733.     if (*obstack_next_free (&util_obstack) == '^'
  3734.         || format !=  OBJC_ENCODE_INLINE_DEFS)
  3735.       {
  3736.         /* we have a reference - this is a NeXT extension--
  3737.            or we don't want the details.  */
  3738.             if (TYPE_NAME (type)
  3739.         && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
  3740.           {
  3741.         obstack_1grow (&util_obstack, '{');
  3742.         obstack_grow (&util_obstack,
  3743.                   IDENTIFIER_POINTER (TYPE_NAME (type)),
  3744.                   strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
  3745.         obstack_1grow (&util_obstack, '}');
  3746.           }
  3747.         else /* we have an untagged structure or a typedef */
  3748.           obstack_grow (&util_obstack, "{?}", 3);
  3749.       }
  3750.     else
  3751.       {
  3752.         tree fields = TYPE_FIELDS (type);
  3753.         obstack_1grow (&util_obstack, '{');
  3754.         for ( ; fields; fields = TREE_CHAIN (fields))
  3755.           encode_field_decl (fields, format);
  3756.         obstack_1grow (&util_obstack, '}');
  3757.       }
  3758.     break;
  3759.       }
  3760.     case UNION_TYPE:
  3761.       {
  3762.     if (*obstack_next_free (&util_obstack) == '^'
  3763.         || format !=  OBJC_ENCODE_INLINE_DEFS)
  3764.       {
  3765.         /* we have a reference - this is a NeXT extension--
  3766.            or we don't want the details.  */
  3767.             if (TYPE_NAME (type)
  3768.         && (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE))
  3769.           {
  3770.         obstack_1grow (&util_obstack, '<');
  3771.         obstack_grow (&util_obstack,
  3772.                   IDENTIFIER_POINTER (TYPE_NAME (type)),
  3773.                   strlen (IDENTIFIER_POINTER (TYPE_NAME (type))));
  3774.         obstack_1grow (&util_obstack, '>');
  3775.           }
  3776.         else /* we have an untagged structure or a typedef */
  3777.           obstack_grow (&util_obstack, "<?>", 3);
  3778.       }
  3779.     else
  3780.       {
  3781.         tree fields = TYPE_FIELDS (type);
  3782.         obstack_1grow (&util_obstack, '<');
  3783.         for ( ; fields; fields = TREE_CHAIN (fields))
  3784.           encode_field_decl (fields, format);
  3785.         obstack_1grow (&util_obstack, '>');
  3786.       }
  3787.     break;
  3788.       }
  3789.  
  3790.     case ENUMERAL_TYPE:
  3791.       obstack_1grow (&util_obstack, 'i');
  3792.       break;
  3793.     }
  3794. }
  3795.  
  3796. /*
  3797.  *  support bitfields, the current version of Objective-C does not support
  3798.  *  them. the string will consist of one or more "b:n"'s where n is an
  3799.  *  integer describing the width of the bitfield. Currently, classes in
  3800.  *  the kit implement a method "-(char *)describeBitfieldStruct:" that
  3801.  *  simulates this...if they do not implement this method, the archiver
  3802.  *  assumes the bitfield is 16 bits wide (padded if necessary) and packed
  3803.  *  according to the GNU compiler. After looking at the "kit", it appears
  3804.  *  that all classes currently rely on this default behavior, rather than
  3805.  *  hand generating this string (which is tedious).
  3806.  */
  3807. static void
  3808. encode_bitfield (width, format)
  3809.      int width;
  3810.      int format;
  3811. {
  3812.   char buffer[40];
  3813.   sprintf (buffer, "b%d", width);
  3814.   obstack_grow (&util_obstack, buffer, strlen (buffer));
  3815. }
  3816.  
  3817. /*
  3818.  *    format will be:
  3819.  *
  3820.  *    OBJC_ENCODE_INLINE_DEFS or OBJC_ENCODE_DONT_INLINE_DEFS
  3821.  */
  3822. static void
  3823. encode_type (type, format)
  3824.      tree type;
  3825.      int format;
  3826. {
  3827.   enum tree_code code = TREE_CODE (type);
  3828.  
  3829.   if (code == INTEGER_TYPE)
  3830.     {
  3831.       if (TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) == 0)
  3832.     {
  3833.       /* unsigned integer types */
  3834.  
  3835.       if (TYPE_MODE (type) == QImode) /* 'C' */
  3836.         obstack_1grow (&util_obstack, 'C');
  3837.       else if (TYPE_MODE (type) == HImode) /* 'S' */
  3838.         obstack_1grow (&util_obstack, 'S');
  3839.       else if (TYPE_MODE (type) == SImode)
  3840.         {
  3841.           if (type == long_unsigned_type_node)
  3842.         obstack_1grow (&util_obstack, 'L'); /* 'L' */
  3843.           else
  3844.         obstack_1grow (&util_obstack, 'I'); /* 'I' */
  3845.         }
  3846.     }
  3847.       else            /* signed integer types */
  3848.     {
  3849.       if (TYPE_MODE (type) == QImode) /* 'c' */
  3850.         obstack_1grow (&util_obstack, 'c');
  3851.       else if (TYPE_MODE (type) == HImode) /* 's' */
  3852.         obstack_1grow (&util_obstack, 's');
  3853.       else if (TYPE_MODE (type) == SImode) /* 'i' */
  3854.         {
  3855.           if (type == long_integer_type_node)
  3856.         obstack_1grow (&util_obstack, 'l'); /* 'l' */
  3857.           else
  3858.         obstack_1grow (&util_obstack, 'i'); /* 'i' */
  3859.         }
  3860.     }
  3861.     }
  3862.   else if (code == REAL_TYPE)
  3863.     {
  3864.       /* floating point types */
  3865.  
  3866.       if (TYPE_MODE (type) == SFmode) /* 'f' */
  3867.     obstack_1grow (&util_obstack, 'f');
  3868.       else if (TYPE_MODE (type) == DFmode
  3869.            || TYPE_MODE (type) == TFmode) /* 'd' */
  3870.     obstack_1grow (&util_obstack, 'd');
  3871.     }
  3872.  
  3873.   else if (code == VOID_TYPE)    /* 'v' */
  3874.     obstack_1grow (&util_obstack, 'v');
  3875.  
  3876.   else if (code == ARRAY_TYPE)
  3877.     encode_array (type, format);
  3878.  
  3879.   else if (code == POINTER_TYPE)
  3880.     encode_pointer (type, format);
  3881.  
  3882.   else if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
  3883.     encode_aggregate (type, format);
  3884.  
  3885.   else if (code == FUNCTION_TYPE) /* '?' */
  3886.     obstack_1grow (&util_obstack, '?');
  3887. }
  3888.  
  3889. static void
  3890. encode_field_decl (field_decl, format)
  3891.      tree field_decl;
  3892.      int format;
  3893. {
  3894.   if (DECL_BIT_FIELD (field_decl))
  3895.     encode_bitfield (DECL_FIELD_SIZE (field_decl), format);
  3896.   else
  3897.     encode_type (TREE_TYPE (field_decl), format);
  3898. }
  3899.  
  3900. static tree
  3901. expr_last (complex_expr)
  3902.      tree complex_expr;
  3903. {
  3904.   tree next;
  3905.  
  3906.   if (complex_expr)
  3907.     while (next = TREE_OPERAND (complex_expr, 0))
  3908.       complex_expr = next;
  3909.   return complex_expr;
  3910. }
  3911.  
  3912. /* The selector of the current method,
  3913.    or NULL if we aren't compiling a method.  */
  3914.  
  3915. tree
  3916. maybe_objc_method_name (decl)
  3917.       tree decl;
  3918. {
  3919.   if (method_context)
  3920.     return METHOD_SEL_NAME (method_context);
  3921.   else
  3922.     return 0;
  3923. }
  3924.  
  3925. /*
  3926.  *  Transform a method definition into a function definition as follows:
  3927.  *
  3928.  *  - synthesize the first two arguments, "self" and "_cmd".
  3929.  */
  3930.  
  3931. void
  3932. start_method_def (method)
  3933.      tree method;
  3934. {
  3935.   tree decl_specs;
  3936.  
  3937.   /* required to implement _msgSuper () */
  3938.   method_context = method;
  3939.   _OBJC_SUPER_decl = NULLT;
  3940.  
  3941.   pushlevel (0);         /* must be called BEFORE "start_function ()" */
  3942.  
  3943.   /* generate prototype declarations for arguments..."new-style" */
  3944.  
  3945.   if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
  3946.     decl_specs = build_tree_list (NULLT, _PRIVATE_record);
  3947.   else
  3948.     /* really a `struct objc_class *'...however we allow people to
  3949.        assign to self...which changes its type midstream.
  3950.        */
  3951.     decl_specs = build_tree_list (NULLT, objc_object_reference);
  3952.  
  3953.   push_parm_decl (build_tree_list (decl_specs,
  3954.                    build1 (INDIRECT_REF, NULLT, self_id)));
  3955.  
  3956. #ifdef OBJC_INT_SELECTORS
  3957.   decl_specs = build_tree_list (NULLT, ridpointers[(int) RID_UNSIGNED]);
  3958.   decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs);
  3959.   push_parm_decl (build_tree_list (decl_specs, _cmd_id));
  3960. #else /* not OBJC_INT_SELECTORS */
  3961.   decl_specs = build_tree_list (NULLT,
  3962.                 xref_tag (RECORD_TYPE,
  3963.                       get_identifier (TAG_SELECTOR)));
  3964.   push_parm_decl (build_tree_list (decl_specs, 
  3965.                    build1 (INDIRECT_REF, NULLT, _cmd_id)));
  3966. #endif /* not OBJC_INT_SELECTORS */
  3967.  
  3968.   /* generate argument declarations if a keyword_decl */
  3969.   if (METHOD_SEL_ARGS (method))
  3970.     {
  3971.       tree arglist = METHOD_SEL_ARGS (method);
  3972.       do
  3973.     {
  3974.       tree arg_spec = TREE_PURPOSE (TREE_TYPE (arglist));
  3975.       tree arg_decl = TREE_VALUE (TREE_TYPE (arglist));
  3976.  
  3977.       if (arg_decl)
  3978.         {
  3979.           tree last_expr = expr_last (arg_decl);
  3980.  
  3981.           /* unite the abstract decl with its name */
  3982.           TREE_OPERAND (last_expr, 0) = KEYWORD_ARG_NAME (arglist);
  3983.           push_parm_decl (build_tree_list (arg_spec, arg_decl));
  3984.           /* unhook...restore the abstract declarator */
  3985.           TREE_OPERAND (last_expr, 0) = NULLT;
  3986.         }
  3987.       else
  3988.         push_parm_decl (build_tree_list (arg_spec, KEYWORD_ARG_NAME (arglist)));
  3989.  
  3990.       arglist = TREE_CHAIN (arglist);
  3991.     }
  3992.       while (arglist);
  3993.     }
  3994.  
  3995.   if (METHOD_ADD_ARGS (method) > (tree)1)
  3996.     {
  3997.       /* we have a variable length selector - in "prototype" format */
  3998.       tree akey = TREE_PURPOSE (METHOD_ADD_ARGS (method));
  3999.       while (akey)
  4000.     {
  4001.       /* this must be done prior to calling pushdecl (). pushdecl () is
  4002.        * going to change our chain on us...
  4003.        */
  4004.       tree nextkey = TREE_CHAIN (akey);
  4005.       pushdecl (akey);
  4006.       akey = nextkey;
  4007.     }
  4008.     }
  4009. }
  4010.  
  4011. static void
  4012. error_with_method (message, mtype, method)
  4013.      char *message;
  4014.      char mtype;
  4015.      tree method;
  4016. {
  4017.   count_error (0);
  4018.   fprintf (stderr, "%s:%d: ",
  4019.        DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
  4020.   bzero (errbuf, BUFSIZE);
  4021.   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
  4022. }
  4023.  
  4024. static void
  4025. warn_with_method (message, mtype, method)
  4026.      char *message;
  4027.      char mtype;
  4028.      tree method;
  4029. {
  4030.   count_error (1);
  4031.   fprintf (stderr, "%s:%d: ",
  4032.        DECL_SOURCE_FILE (method), DECL_SOURCE_LINE (method));
  4033.   bzero (errbuf, BUFSIZE);
  4034.   fprintf (stderr, "%s `%c%s'\n", message, mtype, gen_method_decl (method, errbuf));
  4035. }
  4036.  
  4037. /* return 1 if `method' is consistent with `proto' */
  4038.  
  4039. static int
  4040. comp_method_with_proto (method, proto)
  4041.      tree method, proto;
  4042. {
  4043.   static tree function_type = 0;
  4044.  
  4045.   /* create a function_type node once */
  4046.   if (!function_type)
  4047.     {
  4048.       struct obstack *ambient_obstack = current_obstack;
  4049.       
  4050.       current_obstack = &permanent_obstack;
  4051.       function_type = make_node (FUNCTION_TYPE);
  4052.       current_obstack = ambient_obstack;
  4053.     }
  4054.  
  4055.   /* install argument types - normally set by "build_function_type ()". */
  4056.   TYPE_ARG_TYPES (function_type) = get_arg_type_list (proto, METHOD_DEF, 0);
  4057.  
  4058.   /* install return type */
  4059.   TREE_TYPE (function_type) = groktypename (TREE_TYPE (proto));
  4060.  
  4061.   return comptypes (TREE_TYPE (METHOD_DEFINITION (method)), function_type);
  4062. }
  4063.  
  4064. /* return 1 if `proto1' is consistent with `proto2' */
  4065.  
  4066. static int
  4067. comp_proto_with_proto (proto1, proto2)
  4068.      tree proto1, proto2;
  4069. {
  4070.   static tree function_type1 = 0, function_type2 = 0;
  4071.  
  4072.   /* create a couple function_type node's once */
  4073.   if (!function_type1)
  4074.     {
  4075.       struct obstack *ambient_obstack = current_obstack;
  4076.       
  4077.       current_obstack = &permanent_obstack;
  4078.       function_type1 = make_node (FUNCTION_TYPE);
  4079.       function_type2 = make_node (FUNCTION_TYPE);
  4080.       current_obstack = ambient_obstack;
  4081.     }
  4082.  
  4083.   /* install argument types - normally set by "build_function_type ()". */
  4084.   TYPE_ARG_TYPES (function_type1) = get_arg_type_list (proto1, METHOD_REF, 0);
  4085.   TYPE_ARG_TYPES (function_type2) = get_arg_type_list (proto2, METHOD_REF, 0);
  4086.  
  4087.   /* install return type */
  4088.   TREE_TYPE (function_type1) = groktypename (TREE_TYPE (proto1));
  4089.   TREE_TYPE (function_type2) = groktypename (TREE_TYPE (proto2));
  4090.  
  4091.   return comptypes (function_type1, function_type2);
  4092. }
  4093.  
  4094. /*
  4095.  *  - generate an identifier for the function. the format is "_n_cls",
  4096.  *    where 1 <= n <= nMethods, and cls is the name the implementation we
  4097.  *    are processing.
  4098.  *  - install the return type from the method declaration.
  4099.  *  - if we have a prototype, check for type consistency.
  4100.  */
  4101. static void
  4102. really_start_method (method, parmlist)
  4103.      tree method, parmlist;
  4104. {
  4105.   tree sc_spec, ret_spec, ret_decl, decl_specs;
  4106.   tree method_decl, method_id;
  4107.   char *buf;
  4108.  
  4109.   /* synth the storage class & assemble the return type */
  4110.   sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT);
  4111.   ret_spec = TREE_PURPOSE (TREE_TYPE (method));
  4112.   decl_specs = chainon (sc_spec, ret_spec);
  4113.  
  4114.   if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  4115.     {
  4116.       /* Make sure this is big enough for any plausible method label.  */
  4117.       buf = (char *) alloca (50
  4118.                  + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
  4119.                  + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
  4120. #ifdef OBJC_GEN_METHOD_LABEL
  4121.       OBJC_GEN_METHOD_LABEL (buf,
  4122.                  TREE_CODE (method) == INSTANCE_METHOD_DECL,
  4123.                  IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
  4124.                  NULL,
  4125.                  IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
  4126. #else
  4127.       sprintf (buf, "_%d_%s", ++method_slot,
  4128.            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)));
  4129. #endif
  4130.     }
  4131.   else                /* we have a category */
  4132.     {
  4133.       /* Make sure this is big enough for any plausible method label.  */
  4134.       buf = (char *) alloca (50
  4135.                  + strlen (IDENTIFIER_POINTER (METHOD_SEL_NAME (method)))
  4136.                  + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)))
  4137.                  + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))));
  4138. #ifdef OBJC_GEN_METHOD_LABEL
  4139.       OBJC_GEN_METHOD_LABEL (buf,
  4140.                  TREE_CODE (method) == INSTANCE_METHOD_DECL,
  4141.                  IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
  4142.                  IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)),
  4143.                  IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
  4144. #else
  4145.       sprintf (buf, "_%d_%s_%s", ++method_slot,
  4146.            IDENTIFIER_POINTER (CLASS_NAME (implementation_context)),
  4147.            IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context)));
  4148. #endif
  4149.     }
  4150.  
  4151.   method_id = get_identifier (buf);
  4152.  
  4153.   method_decl = build_nt (CALL_EXPR, method_id, parmlist, NULLT);
  4154.  
  4155.   /* check the declarator portion of the return type for the method */
  4156.   if (ret_decl = TREE_VALUE (TREE_TYPE (method)))
  4157.     {
  4158.       /*
  4159.        * unite the complex decl (specified in the abstract decl) with the
  4160.        * function decl just synthesized...(int *), (int (*)()), (int (*)[]).
  4161.        */
  4162.       tree save_expr = expr_last (ret_decl);
  4163.  
  4164.       TREE_OPERAND (save_expr, 0) = method_decl;
  4165.       method_decl = ret_decl;
  4166.       /* fool the parser into thinking it is starting a function */
  4167.       start_function (decl_specs, method_decl, 0);
  4168.       /* unhook...this has the effect of restoring the abstract declarator */
  4169.       TREE_OPERAND (save_expr, 0) = NULLT;
  4170.     }
  4171.   else
  4172.     {
  4173.       TREE_VALUE (TREE_TYPE (method)) = method_decl;
  4174.       /* fool the parser into thinking it is starting a function */
  4175.       start_function (decl_specs, method_decl, 0);
  4176.       /* unhook...this has the effect of restoring the abstract declarator */
  4177.       TREE_VALUE (TREE_TYPE (method)) = NULLT;
  4178.     }
  4179.  
  4180.   METHOD_DEFINITION (method) = current_function_decl;
  4181.  
  4182.   /* check consistency...start_function (), pushdecl (), duplicate_decls (). */
  4183.  
  4184.   if (implementation_template != implementation_context)
  4185.     {
  4186.       tree chain, proto;
  4187.  
  4188.       if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
  4189.     chain = CLASS_NST_METHODS (implementation_template);
  4190.       else
  4191.     chain = CLASS_CLS_METHODS (implementation_template);
  4192.  
  4193.       if (proto = lookup_method (chain, METHOD_SEL_NAME (method)))
  4194.     {
  4195.       if (!comp_method_with_proto (method, proto))
  4196.         {
  4197.           fprintf (stderr, "%s: In method `%s'\n", input_filename,
  4198.                IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
  4199.           if (TREE_CODE (method) == INSTANCE_METHOD_DECL)
  4200.         {
  4201.           error_with_method ("conflicting types for", '-', method);
  4202.           error_with_method ("previous declaration of", '-', proto);
  4203.         }
  4204.           else
  4205.         {
  4206.           error_with_method ("conflicting types for", '+', method);
  4207.           error_with_method ("previous declaration of", '+', proto);
  4208.         }
  4209.         }
  4210.     }
  4211.     }
  4212. }
  4213.  
  4214. /*
  4215.  * the following routine is always called...this "architecture" is to
  4216.  * accommodate "old-style" variable length selectors.
  4217.  *
  4218.  *    - a:a b:b // prototype  ; id c; id d; // old-style
  4219.  */
  4220. void
  4221. continue_method_def ()
  4222. {
  4223.   tree parmlist;
  4224.  
  4225.   if (METHOD_ADD_ARGS (method_context) == (tree)1)
  4226.     /*
  4227.      * we have a `, ...' immediately following the selector.
  4228.      */
  4229.     parmlist = get_parm_info (0);
  4230.   else
  4231.     parmlist = get_parm_info (1); /* place a `void_at_end' */
  4232.  
  4233.   /* set self_decl from the first argument...this global is used by
  4234.    * build_ivar_reference ().build_indirect_ref ().
  4235.    */
  4236.   self_decl = TREE_PURPOSE (parmlist);
  4237.  
  4238.   poplevel (0, 0, 0);        /* must be called BEFORE "start_function ()" */
  4239.  
  4240.   really_start_method (method_context, parmlist);
  4241.  
  4242.   store_parm_decls ();        /* must be called AFTER "start_function ()" */
  4243. }
  4244.  
  4245. void
  4246. add_objc_decls ()
  4247. {
  4248.   if (!_OBJC_SUPER_decl)
  4249.     _OBJC_SUPER_decl = start_decl (get_identifier (_TAG_SUPER),
  4250.                    build_tree_list (NULLT, objc_super_template), 0);
  4251.  
  4252.   /* this prevents `unused variable' warnings when compiling with `-Wall' */
  4253.   DECL_IN_SYSTEM_HEADER (_OBJC_SUPER_decl) = 1;
  4254. }
  4255.  
  4256. /*
  4257.  *    _n_Method (id self, SEL sel, ...)
  4258.  *    {
  4259.  *        struct objc_super _S;
  4260.  *
  4261.  *        _msgSuper ((_S.self = self, _S.class = _cls, &_S), ...);
  4262.  *    }
  4263.  */
  4264. tree
  4265. get_super_receiver ()
  4266. {
  4267.   if (method_context)
  4268.     {
  4269.       tree super_expr, super_expr_list;
  4270.  
  4271.       /* set receiver to self */
  4272.       super_expr = build_component_ref (_OBJC_SUPER_decl, self_id);
  4273.       super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
  4274.       super_expr_list = build_tree_list (NULLT, super_expr);
  4275.  
  4276.       /* set class to begin searching */
  4277.       super_expr = build_component_ref (_OBJC_SUPER_decl, get_identifier ("class"));
  4278.  
  4279.       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  4280.     {
  4281.       /* [_cls, __cls]Super are "pre-built" in synth_foward_declarations () */
  4282.  
  4283.       if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
  4284.         super_expr = build_modify_expr (super_expr, NOP_EXPR, _clsSuper_ref);
  4285.       else
  4286.         super_expr = build_modify_expr (super_expr, NOP_EXPR, __clsSuper_ref);
  4287.     }
  4288.       else            /* we have a category... */
  4289.     {
  4290.       tree params, super_name = CLASS_SUPER_NAME (implementation_template);
  4291.       tree funcCall;
  4292.  
  4293.       if (!super_name)  /* Barf if super used in a category of Object. */
  4294.         {
  4295.           error("no super class declared in interface for `%s'",
  4296.             IDENTIFIER_POINTER (CLASS_NAME (implementation_template)));
  4297.           return error_mark_node;
  4298.         }
  4299.  
  4300.       add_class_reference (super_name);
  4301.  
  4302.       params = build_tree_list (NULLT,
  4303.                     my_build_string (IDENTIFIER_LENGTH (super_name) + 1,
  4304.                              IDENTIFIER_POINTER (super_name)));
  4305.  
  4306.       if (TREE_CODE (method_context) == INSTANCE_METHOD_DECL)
  4307.         funcCall = build_function_call (objc_getClass_decl, params);
  4308.       else
  4309.         funcCall = build_function_call (objc_getMetaClass_decl, params);
  4310.  
  4311.       /* cast! */
  4312.       TREE_TYPE (funcCall) = TREE_TYPE (_clsSuper_ref);
  4313.       super_expr = build_modify_expr (super_expr, NOP_EXPR, funcCall);
  4314.     }
  4315.       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
  4316.  
  4317.       super_expr = build_unary_op (ADDR_EXPR, _OBJC_SUPER_decl, 0);
  4318.       chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr));
  4319.  
  4320.       return build_compound_expr (super_expr_list);
  4321.     }
  4322.   else
  4323.     {
  4324.       error ("[super ...] must appear in a method context");
  4325.       return error_mark_node;
  4326.     }
  4327. }
  4328.  
  4329. static tree
  4330. encode_method_def (func_decl)
  4331.       tree func_decl;
  4332. {
  4333.   tree parms;
  4334.   int stack_size = 0;
  4335.   char buffer[40];
  4336.   tree result;
  4337.  
  4338.   /* return type */
  4339.   encode_type (TREE_TYPE (TREE_TYPE (func_decl)),
  4340.            OBJC_ENCODE_DONT_INLINE_DEFS);
  4341.   /* stack size */
  4342.   for (parms = DECL_ARGUMENTS (func_decl); parms;
  4343.        parms = TREE_CHAIN (parms))
  4344.     stack_size += TREE_INT_CST_LOW (TYPE_SIZE (DECL_ARG_TYPE (parms)))
  4345.           / BITS_PER_UNIT;
  4346.  
  4347.   sprintf (buffer, "%d", stack_size);
  4348.   obstack_grow (&util_obstack, buffer, strlen (buffer));
  4349.  
  4350.   /* argument types */
  4351.   for (parms = DECL_ARGUMENTS (func_decl); parms;
  4352.        parms = TREE_CHAIN (parms))
  4353.     {
  4354.       int offset_in_bytes;
  4355.   
  4356.       /* type */ 
  4357.       encode_type (TREE_TYPE (parms), OBJC_ENCODE_DONT_INLINE_DEFS);
  4358.   
  4359.       /* compute offset */
  4360.       if (GET_CODE (DECL_INCOMING_RTL (parms)) == MEM)
  4361.         {
  4362.       rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
  4363.       
  4364.       /* ??? Here we assume that the parm address is indexed
  4365.           off the frame pointer or arg pointer.
  4366.           If that is not true, we produce meaningless results,
  4367.           but do not crash.  */
  4368.       if (GET_CODE (addr) == PLUS
  4369.           && GET_CODE (XEXP (addr, 1)) == CONST_INT)
  4370.         offset_in_bytes = INTVAL (XEXP (addr, 1));
  4371.       else
  4372.         offset_in_bytes = 0;
  4373.       
  4374.       /* This is the case where the parm is passed as an int or double
  4375.           and it is converted to a char, short or float and stored back
  4376.           in the parmlist.  In this case, describe the parm
  4377.           with the variable's declared type, and adjust the address
  4378.           if the least significant bytes (which we are using) are not
  4379.           the first ones.  */
  4380. #if BYTES_BIG_ENDIAN
  4381.       if (TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
  4382.         offset_in_bytes += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
  4383.                 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
  4384. #endif
  4385.     }
  4386.       else
  4387.         offset_in_bytes = 0;
  4388.       
  4389.       /* The "+ 4" is a total hack to account for the return pc and
  4390.          saved fp on the 68k.  We should redefine this format! */
  4391.       sprintf (buffer, "%d", offset_in_bytes + 8);
  4392.       obstack_grow (&util_obstack, buffer, strlen (buffer));
  4393.     }
  4394.  
  4395.   result = get_identifier (obstack_finish (&util_obstack));
  4396.   obstack_free (&util_obstack, util_firstobj);
  4397.   return result;
  4398. }
  4399.  
  4400. void
  4401. finish_method_def ()
  4402. {
  4403.   METHOD_ENCODING (method_context) =
  4404.     encode_method_def (current_function_decl);
  4405.  
  4406.   finish_function (0);
  4407.  
  4408.   /* this must be done AFTER finish_function, since the optimizer may
  4409.      find "may be used before set" errors.  */
  4410.   method_context = NULLT;    /* required to implement _msgSuper () */
  4411. }
  4412.  
  4413. int
  4414. lang_report_error_function (decl)
  4415.       tree decl;
  4416. {
  4417.   if (method_context)
  4418.     {
  4419.       fprintf (stderr, "In method `%s'\n",
  4420.            IDENTIFIER_POINTER (METHOD_SEL_NAME (method_context)));
  4421.       return 1;
  4422.     }
  4423.   else
  4424.     return 0;
  4425. }
  4426.  
  4427. static int
  4428. is_complex_decl (type)
  4429.      tree type;
  4430. {
  4431.   return (TREE_CODE (type) == ARRAY_TYPE
  4432.       || TREE_CODE (type) == FUNCTION_TYPE
  4433.       || TREE_CODE (type) == POINTER_TYPE);
  4434. }
  4435.  
  4436.  
  4437. /* Code to convert a decl node into text for a declaration in C.  */
  4438.  
  4439. static char tmpbuf[256];
  4440.  
  4441. static void
  4442. adorn_decl (decl, str)
  4443.      tree decl;
  4444.      char *str;
  4445. {
  4446.   enum tree_code code = TREE_CODE (decl);
  4447.  
  4448.   if (code == ARRAY_REF)
  4449.     {
  4450.       tree anIntCst = TREE_OPERAND (decl, 1);
  4451.  
  4452.       sprintf (str + strlen (str), "[%d]", TREE_INT_CST_LOW (anIntCst));
  4453.     }
  4454.   else if (code == ARRAY_TYPE)
  4455.     {
  4456.       tree anIntCst = TYPE_SIZE (decl);
  4457.       tree array_of = TREE_TYPE (decl);
  4458.  
  4459.       sprintf (str + strlen (str), "[%d]",
  4460.            TREE_INT_CST_LOW (anIntCst)/TREE_INT_CST_LOW (TYPE_SIZE (array_of)));
  4461.     }
  4462.   else if (code == CALL_EXPR)
  4463.     strcat (str, "()");
  4464.   else if (code == FUNCTION_TYPE)
  4465.     {
  4466.       tree chain  = TYPE_ARG_TYPES (decl); /* a list of types */
  4467.       strcat (str, "(");
  4468.       while (chain && TREE_VALUE (chain) != void_type_node)
  4469.     {
  4470.       gen_declaration (TREE_VALUE (chain), str);
  4471.       chain = TREE_CHAIN (chain);
  4472.       if (chain && TREE_VALUE (chain) != void_type_node)
  4473.         strcat (str, ",");
  4474.     }
  4475.       strcat (str, ")");
  4476.     }
  4477.   else
  4478.     {
  4479.       strcpy (tmpbuf, "*"); strcat (tmpbuf, str);
  4480.       strcpy (str, tmpbuf);
  4481.     }
  4482. }
  4483.  
  4484. static char *
  4485. gen_declarator (decl, buf, name)
  4486.      tree decl;
  4487.      char *buf;
  4488.      char *name;
  4489. {
  4490.   if (decl)
  4491.     {
  4492.       enum tree_code code = TREE_CODE (decl);
  4493.       char *str;
  4494.       tree op;
  4495.       int wrap = 0;
  4496.  
  4497.       switch (code)
  4498.     {
  4499.     case ARRAY_REF: case INDIRECT_REF: case CALL_EXPR:
  4500.       {
  4501.         op = TREE_OPERAND (decl, 0);
  4502.  
  4503.         /* we have a pointer to a function or array...(*)(), (*)[] */
  4504.         if ((code == ARRAY_REF || code == CALL_EXPR) &&
  4505.         (op && TREE_CODE (op) == INDIRECT_REF))
  4506.           wrap = 1;
  4507.  
  4508.         str = gen_declarator (op, buf, name);
  4509.  
  4510.         if (wrap)
  4511.           {
  4512.         strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
  4513.         strcpy (str, tmpbuf);
  4514.           }
  4515.  
  4516.         adorn_decl (decl, str);
  4517.         break;
  4518.       }
  4519.     case ARRAY_TYPE: case FUNCTION_TYPE: case POINTER_TYPE:
  4520.       {
  4521.         str = strcpy (buf, name);
  4522.  
  4523.         /* this clause is done iteratively...rather than recursively */
  4524.         do
  4525.           {
  4526.         op = is_complex_decl (TREE_TYPE (decl))
  4527.           ? TREE_TYPE (decl)
  4528.             : NULLT;
  4529.  
  4530.         adorn_decl (decl, str);
  4531.  
  4532.         /* we have a pointer to a function or array...(*)(), (*)[] */
  4533.         if ((code == POINTER_TYPE) &&
  4534.             (op && (TREE_CODE (op) == FUNCTION_TYPE
  4535.                 || TREE_CODE (op) == ARRAY_TYPE)))
  4536.           {
  4537.             strcpy (tmpbuf, "("); strcat (tmpbuf, str); strcat (tmpbuf, ")");
  4538.             strcpy (str, tmpbuf);
  4539.           }
  4540.  
  4541.         decl = is_complex_decl (TREE_TYPE (decl))
  4542.           ? TREE_TYPE (decl)
  4543.             : NULLT;
  4544.           }
  4545.         while (decl && (code = TREE_CODE (decl)));
  4546.  
  4547.         break;
  4548.       }
  4549.     case IDENTIFIER_NODE:
  4550.       /* will only happen if we are processing a "raw" expr-decl. */
  4551.       return strcpy (buf, IDENTIFIER_POINTER (decl));
  4552.     }
  4553.  
  4554.       return str;
  4555.     }
  4556.   else                /* we have an abstract declarator or a _DECL node */
  4557.     {
  4558.       return strcpy (buf, name);
  4559.     }
  4560. }
  4561.  
  4562. static void
  4563. gen_declspecs (declspecs, buf, raw)
  4564.      tree declspecs;
  4565.      char *buf;
  4566.      int raw;
  4567. {
  4568.   if (raw)
  4569.     {
  4570.       tree chain;
  4571.  
  4572.       for (chain = declspecs; chain; chain = TREE_CHAIN (chain))
  4573.     {
  4574.       tree aspec = TREE_VALUE (chain);
  4575.  
  4576.       if (TREE_CODE (aspec) == IDENTIFIER_NODE)
  4577.         strcat (buf, IDENTIFIER_POINTER (aspec));
  4578.       else if (TREE_CODE (aspec) == RECORD_TYPE)
  4579.         {
  4580.           if (TYPE_NAME (aspec))
  4581.         {
  4582.           if (!TREE_STATIC_TEMPLATE (aspec))
  4583.             strcat (buf, "struct ");
  4584.           strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
  4585.         }
  4586.           else
  4587.         strcat (buf, "untagged struct");
  4588.         }
  4589.       else if (TREE_CODE (aspec) == UNION_TYPE)
  4590.         {
  4591.           if (TYPE_NAME (aspec))
  4592.         {
  4593.           if (!TREE_STATIC_TEMPLATE (aspec))
  4594.             strcat (buf, "union ");
  4595.           strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
  4596.         }
  4597.           else
  4598.         strcat (buf, "untagged union");
  4599.         }
  4600.       else if (TREE_CODE (aspec) == ENUMERAL_TYPE)
  4601.         {
  4602.           if (TYPE_NAME (aspec))
  4603.         {
  4604.           if (!TREE_STATIC_TEMPLATE (aspec))
  4605.             strcat (buf, "enum ");
  4606.           strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (aspec)));
  4607.         }
  4608.           else
  4609.         strcat (buf, "untagged enum");
  4610.         }
  4611.       strcat (buf, " ");
  4612.     }
  4613.     }
  4614.   else
  4615.     switch (TREE_CODE (declspecs))
  4616.       {
  4617.     /* type specifiers */
  4618.  
  4619.       case INTEGER_TYPE:    /* signed integer types */
  4620.  
  4621.         if (declspecs == short_integer_type_node) /* 's' */
  4622.           strcat (buf, "short int ");
  4623.         else if (declspecs == integer_type_node) /* 'i' */
  4624.           strcat (buf, "int ");
  4625.         else if (declspecs == long_integer_type_node) /* 'l' */
  4626.           strcat (buf, "long int ");
  4627.         else if (declspecs == signed_char_type_node || /* 'c' */
  4628.                declspecs == char_type_node)
  4629.           strcat (buf, "char ");
  4630.  
  4631.         /* unsigned integer types */
  4632.  
  4633.         else if (declspecs == short_unsigned_type_node)    /* 'S' */
  4634.           strcat (buf, "unsigned short ");
  4635.         else if (declspecs == unsigned_type_node) /* 'I' */
  4636.           strcat (buf, "unsigned int ");
  4637.         else if (declspecs == long_unsigned_type_node) /* 'L' */
  4638.           strcat (buf, "unsigned long ");
  4639.         else if (declspecs == unsigned_char_type_node) /* 'C' */
  4640.           strcat (buf, "unsigned char ");
  4641.     break;
  4642.  
  4643.       case REAL_TYPE:        /* floating point types */
  4644.  
  4645.         if (declspecs == float_type_node) /* 'f' */
  4646.           strcat (buf, "float ");
  4647.         else if (declspecs == double_type_node)    /* 'd' */
  4648.           strcat (buf, "double ");
  4649.     else if (declspecs == long_double_type_node) /* 'd' */
  4650.           strcat (buf, "long double ");
  4651.     break;
  4652.  
  4653.       case RECORD_TYPE:
  4654.     if (!TREE_STATIC_TEMPLATE (declspecs))
  4655.       strcat (buf, "struct ");
  4656.     if (TYPE_NAME (declspecs) &&
  4657.         (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
  4658.       {
  4659.         strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
  4660.         strcat (buf, " ");
  4661.       }
  4662.     break;
  4663.       case UNION_TYPE:
  4664.     strcat (buf, "union ");
  4665.     if (TYPE_NAME (declspecs) &&
  4666.         (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
  4667.       {
  4668.         strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
  4669.         strcat (buf, " ");
  4670.       }
  4671.     break;
  4672.       case ENUMERAL_TYPE:
  4673.     strcat (buf, "enum ");
  4674.     if (TYPE_NAME (declspecs) &&
  4675.         (TREE_CODE (TYPE_NAME (declspecs)) == IDENTIFIER_NODE))
  4676.       {
  4677.         strcat (buf, IDENTIFIER_POINTER (TYPE_NAME (declspecs)));
  4678.         strcat (buf, " ");
  4679.       }
  4680.     break;
  4681.       case VOID_TYPE:
  4682.     strcat (buf, "void ");
  4683.       }
  4684. }
  4685.  
  4686. static char *
  4687. gen_declaration (atype_or_adecl, buf)
  4688.      tree atype_or_adecl;
  4689.      char *buf;
  4690. {
  4691.   char declbuf[256];
  4692.  
  4693.   if (TREE_CODE (atype_or_adecl) == TREE_LIST)
  4694.     {
  4695.       tree declspecs;        /* "identifier_node", "record_type" */
  4696.       tree declarator;        /* "array_ref", "indirect_ref", "call_expr"... */
  4697.  
  4698.       /* we have a "raw", abstract declarator (typename) */
  4699.       declarator = TREE_VALUE (atype_or_adecl);
  4700.       declspecs  = TREE_PURPOSE (atype_or_adecl);
  4701.  
  4702.       gen_declspecs (declspecs, buf, 1);
  4703.       strcat (buf, gen_declarator (declarator, declbuf, ""));
  4704.     }
  4705.   else
  4706.     {
  4707.       tree atype;
  4708.       tree declspecs;        /* "integer_type", "real_type", "record_type"... */
  4709.       tree declarator;        /* "array_type", "function_type", "pointer_type". */
  4710.  
  4711.       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
  4712.       || TREE_CODE (atype_or_adecl) == PARM_DECL
  4713.       || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
  4714.     atype = TREE_TYPE (atype_or_adecl);
  4715.       else
  4716.     atype = atype_or_adecl;    /* assume we have a *_type node */
  4717.  
  4718.       if (is_complex_decl (atype))
  4719.     {
  4720.       tree chain;
  4721.  
  4722.       /* get the declaration specifier...it is at the end of the list */
  4723.       declarator = chain = atype;
  4724.       do
  4725.         chain = TREE_TYPE (chain); /* not TREE_CHAIN (chain); */
  4726.       while (is_complex_decl (chain));
  4727.       declspecs = chain;
  4728.     }
  4729.       else
  4730.     {
  4731.       declspecs = atype;
  4732.       declarator = NULLT;
  4733.     }
  4734.  
  4735.       gen_declspecs (declspecs, buf, 0);
  4736.  
  4737.       if (TREE_CODE (atype_or_adecl) == FIELD_DECL
  4738.       || TREE_CODE (atype_or_adecl) == PARM_DECL
  4739.       || TREE_CODE (atype_or_adecl) == FUNCTION_DECL)
  4740.     {
  4741.       if (declarator)
  4742.         {
  4743.           strcat (buf, gen_declarator (declarator, declbuf,
  4744.                        IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl))));
  4745.         }
  4746.       else
  4747.         strcat (buf, IDENTIFIER_POINTER (DECL_NAME (atype_or_adecl)));
  4748.     }
  4749.       else
  4750.     {
  4751.       strcat (buf, gen_declarator (declarator, declbuf, ""));
  4752.     }
  4753.     }
  4754.   return buf;
  4755. }
  4756.  
  4757. #define RAW_TYPESPEC(meth) (TREE_VALUE (TREE_PURPOSE (TREE_TYPE (meth))))
  4758.  
  4759. static char *
  4760. gen_method_decl (method, buf)
  4761.      tree method;
  4762.      char *buf;
  4763. {
  4764.   tree chain;
  4765.  
  4766.   if (RAW_TYPESPEC (method) != objc_object_reference)
  4767.     {
  4768.       strcpy (buf, "(");
  4769.       gen_declaration (TREE_TYPE (method), buf);
  4770.       strcat (buf, ")");
  4771.     }
  4772.  
  4773.   chain = METHOD_SEL_ARGS (method);
  4774.   if (chain)
  4775.     {                /* we have a chain of keyword_decls */
  4776.       do
  4777.         {
  4778.       if (KEYWORD_KEY_NAME (chain))
  4779.         strcat (buf, IDENTIFIER_POINTER (KEYWORD_KEY_NAME (chain)));
  4780.  
  4781.       strcat (buf, ":");
  4782.       if (RAW_TYPESPEC (chain) != objc_object_reference)
  4783.         {
  4784.           strcat (buf, "(");
  4785.           gen_declaration (TREE_TYPE (chain), buf);
  4786.           strcat (buf, ")");
  4787.         }
  4788.       strcat (buf, IDENTIFIER_POINTER (KEYWORD_ARG_NAME (chain)));
  4789.       if (chain = TREE_CHAIN (chain))
  4790.         strcat (buf, " ");
  4791.         }
  4792.       while (chain);
  4793.  
  4794.       if (METHOD_ADD_ARGS (method) == (tree)1)
  4795.         strcat (buf, ", ...");
  4796.       else if (METHOD_ADD_ARGS (method))
  4797.         {            /* we have a tree list node as generate by `get_parm_info ()' */
  4798.       chain  = TREE_PURPOSE (METHOD_ADD_ARGS (method));
  4799.           /* know we have a chain of parm_decls */
  4800.           while (chain)
  4801.             {
  4802.           strcat (buf, ", ");
  4803.           gen_declaration (chain, buf);
  4804.           chain = TREE_CHAIN (chain);
  4805.             }
  4806.     }
  4807.     }
  4808.   else                /* we have a unary selector */
  4809.     {
  4810.       strcat (buf, IDENTIFIER_POINTER (METHOD_SEL_NAME (method)));
  4811.     }
  4812.  
  4813.   return buf;
  4814. }
  4815.  
  4816. void
  4817. gen_prototype (fp, decl)
  4818.      FILE *fp;
  4819.      tree decl;
  4820. {
  4821.   /* we have a function definition - generate prototype */
  4822.   bzero (errbuf, BUFSIZE);
  4823.   gen_declaration (decl, errbuf);
  4824.   fprintf (fp, "%s;\n", errbuf);
  4825. }
  4826. /*
  4827.  *  debug info...
  4828.  */
  4829. static void
  4830. dump_interface (fp, chain)
  4831.      FILE *fp;
  4832.      tree chain;
  4833. {
  4834.   char *buf = (char *)xmalloc (256);
  4835.   char *my_name = IDENTIFIER_POINTER (CLASS_NAME (chain));
  4836.   tree ivar_decls = CLASS_RAW_IVARS (chain);
  4837.   tree nst_methods = CLASS_NST_METHODS (chain);
  4838.   tree cls_methods = CLASS_CLS_METHODS (chain);
  4839.  
  4840.   fprintf (fp, "\n@interface %s", my_name);
  4841.  
  4842.   if (CLASS_SUPER_NAME (chain))
  4843.     {
  4844.       char *super_name = IDENTIFIER_POINTER (CLASS_SUPER_NAME (chain));
  4845.       fprintf (fp, " : %s\n", super_name);
  4846.     }
  4847.   else
  4848.     fprintf (fp, "\n");
  4849.  
  4850.   if (ivar_decls)
  4851.     {
  4852.       fprintf (fp, "{\n");
  4853.       do
  4854.     {
  4855.       bzero (buf, 256);
  4856.       fprintf (fp, "\t%s;\n", gen_declaration (ivar_decls, buf));
  4857.       ivar_decls = TREE_CHAIN (ivar_decls);
  4858.     }
  4859.       while (ivar_decls);
  4860.       fprintf (fp, "}\n");
  4861.     }
  4862.  
  4863.   while (nst_methods)
  4864.     {
  4865.       bzero (buf, 256);
  4866.       fprintf (fp, "- %s;\n", gen_method_decl (nst_methods, buf));
  4867.       nst_methods = TREE_CHAIN (nst_methods);
  4868.     }
  4869.  
  4870.   while (cls_methods)
  4871.     {
  4872.       bzero (buf, 256);
  4873.       fprintf (fp, "+ %s;\n", gen_method_decl (cls_methods, buf));
  4874.       cls_methods = TREE_CHAIN (cls_methods);
  4875.     }
  4876.   fprintf (fp, "\n@end");
  4877. }
  4878.  
  4879. void
  4880. init_objc ()
  4881. {
  4882.   /* Add the special tree codes of Objective C to the tables.  */
  4883.  
  4884.   gcc_obstack_init (&util_obstack);
  4885.   util_firstobj = (char *) obstack_finish (&util_obstack);
  4886.  
  4887.   tree_code_type
  4888.     = (char **) realloc (tree_code_type,
  4889.              sizeof (char *) * LAST_OBJC_TREE_CODE);
  4890.   tree_code_length
  4891.     = (int *) realloc (tree_code_length,
  4892.                sizeof (int) * LAST_OBJC_TREE_CODE);
  4893.   tree_code_name
  4894.     = (char **) realloc (tree_code_name,
  4895.              sizeof (char *) * LAST_OBJC_TREE_CODE);
  4896.   bcopy (objc_tree_code_type,
  4897.      tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
  4898.      (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
  4899.       * sizeof (char *)));
  4900.   bcopy (objc_tree_code_length,
  4901.      tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
  4902.      (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
  4903.       * sizeof (int)));
  4904.   bcopy (objc_tree_code_name,
  4905.      tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
  4906.      (((int) LAST_OBJC_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE)
  4907.       * sizeof (char *)));
  4908.  
  4909.   errbuf = (char *)xmalloc (BUFSIZE);
  4910.   hash_init ();
  4911.   synth_module_prologue ();
  4912. }
  4913.  
  4914. void
  4915. finish_objc ()
  4916. {
  4917.   struct imp_entry *impent;
  4918.   tree chain;
  4919.  
  4920.   generate_forward_declaration_to_string_table ();
  4921.  
  4922. #ifdef OBJC_PROLOGUE
  4923.   OBJC_PROLOGUE;
  4924. #endif
  4925.  
  4926.   if (implementation_context || sel_refdef_chain)
  4927.     generate_objc_symtab_decl ();
  4928.  
  4929.   for (impent = imp_list; impent; impent = impent->next)
  4930.     {
  4931.       implementation_context = impent->imp_context;
  4932.       implementation_template = impent->imp_template;
  4933.  
  4934.       _OBJC_CLASS_decl = impent->class_decl;
  4935.       _OBJC_METACLASS_decl = impent->meta_decl;
  4936.  
  4937.       if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE)
  4938.     {
  4939.       /* all of the following reference the string pool...  */
  4940.       generate_ivar_lists ();
  4941.       generate_dispatch_tables ();
  4942.       generate_shared_structures ();
  4943.     }
  4944.       else
  4945.     {
  4946.       generate_dispatch_tables ();
  4947.       generate_category (implementation_context);
  4948.     }
  4949.     }
  4950.  
  4951.   if (sel_ref_chain)
  4952.     build_selector_translation_table ();
  4953.  
  4954.   if (implementation_context || sel_refdef_chain)
  4955.     {
  4956.       /* Arrange for Objc data structures to be initialized at run time.  */
  4957.  
  4958.       char *init_name = build_module_descriptor ();
  4959. #if 0
  4960.       if (init_name)
  4961.     assemble_constructor (init_name);
  4962. #endif
  4963.     }
  4964.  
  4965.   /* dump the string table last */
  4966.  
  4967.   if (sel_refdef_chain)
  4968.     {
  4969.       build_message_selector_pool ();
  4970.     }
  4971.  
  4972.   /* dump the class references...this forces the appropriate classes
  4973.      to be linked into the executable image, preserving unix archive
  4974.      semantics...this can be removed when we move to a more dynamically
  4975.      linked environment
  4976.      */
  4977.   for (chain = cls_ref_chain; chain; chain = TREE_CHAIN (chain))
  4978.     handle_class_ref (chain);
  4979.  
  4980.   for (impent = imp_list; impent; impent = impent->next)
  4981.     handle_impent (impent);
  4982.  
  4983. #if 0 /* If GAS has such a bug, let's fix it.  */
  4984.   /*** this fixes a gross bug in the assembler...it `expects' #APP to have
  4985.    *** a matching #NO_APP, or it crashes (sometimes). app_disable () will
  4986.    *** insure this is the case. 5/19/89, s.naroff.
  4987.    ***/
  4988.   if (cls_ref_chain || imp_list)
  4989.     app_disable ();
  4990. #endif
  4991.  
  4992.   if (flag_gen_declaration)
  4993.     {
  4994.       add_class (implementation_context);
  4995.       dump_interface (gen_declaration_file, implementation_context);
  4996.     }
  4997.   if (warn_selector)
  4998.     {
  4999.       int slot;
  5000.       
  5001.       /* Run through the selector hash tables and print a warning for any
  5002.          selector which has multiple methods. */
  5003.       
  5004.       for (slot = 0; slot < SIZEHASHTABLE; slot++)
  5005.         {
  5006.       hash hsh;
  5007.       
  5008.       for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
  5009.         {
  5010.           if (hsh->list)
  5011.             {
  5012.               tree meth = hsh->key;
  5013.               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
  5014.                   ? '-' : '+';
  5015.               attr loop;
  5016.           
  5017.           warning ("potential selector conflict for method `%s'",
  5018.                IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
  5019.               warn_with_method ("found", type, meth);
  5020.               for (loop = hsh->list; loop; loop = loop->next)
  5021.                 warn_with_method ("found", type, loop->value);
  5022.             }
  5023.         }
  5024.     }
  5025.     
  5026.       for (slot = 0; slot < SIZEHASHTABLE; slot++)
  5027.         {
  5028.       hash hsh;
  5029.       
  5030.       for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
  5031.         {
  5032.           if (hsh->list)
  5033.             {
  5034.               tree meth = hsh->key;
  5035.               char type = (TREE_CODE (meth) == INSTANCE_METHOD_DECL)
  5036.                   ? '-' : '+';
  5037.               attr loop;
  5038.           
  5039.           warning ("potential selector conflict for method `%s'",
  5040.                IDENTIFIER_POINTER (METHOD_SEL_NAME (meth)));
  5041.               warn_with_method ("found", type, meth);
  5042.               for (loop = hsh->list; loop; loop = loop->next)
  5043.                 warn_with_method ("found", type, loop->value);
  5044.             }
  5045.         }
  5046.     }
  5047.     }
  5048. }
  5049.  
  5050. /* Subroutines of finish_objc.  */
  5051.  
  5052. handle_class_ref (chain)
  5053.      tree chain;
  5054. {
  5055.   tree decl;
  5056.   char *string
  5057.     = (char *) alloca (strlen (IDENTIFIER_POINTER (TREE_VALUE (chain))) + 30);
  5058.  
  5059.   sprintf (string, ".objc_class_name_%s",
  5060.        IDENTIFIER_POINTER (TREE_VALUE (chain)));
  5061.  
  5062.   /* Make a decl for this name, so we can use its address in a tree.  */
  5063.   decl = build_decl (VAR_DECL, get_identifier (string), char_type_node);
  5064.   DECL_EXTERNAL (decl) = 1;
  5065.   TREE_PUBLIC (decl) = 1;
  5066.  
  5067.   pushdecl (decl);
  5068.   rest_of_decl_compilation (decl, 0, 0, 0);
  5069.  
  5070.   /* Make following constant read-only (why not)?  */
  5071.   text_section ();
  5072.  
  5073.   /* Output a constant to reference this address.  */
  5074.   output_constant (build1 (ADDR_EXPR, string_type_node, decl),
  5075.            int_size_in_bytes (string_type_node));
  5076. }
  5077.  
  5078. handle_impent (impent)
  5079.      struct imp_entry *impent;
  5080. {
  5081.   implementation_context = impent->imp_context;
  5082.   implementation_template = impent->imp_template;
  5083.  
  5084.   if (TREE_CODE (impent->imp_context) == IMPLEMENTATION_TYPE)
  5085.     {
  5086.       char *string
  5087.     = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context))) + 30);
  5088.  
  5089.       sprintf (string, ".objc_class_name_%s",
  5090.            IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)));
  5091.       assemble_global (string);
  5092.       assemble_label (string);
  5093.     }
  5094.   else if (TREE_CODE (impent->imp_context) == CATEGORY_TYPE)
  5095.     {
  5096.       char *string
  5097.     = (char *) alloca (strlen (IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)))
  5098.                + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)))
  5099.                + 30);
  5100.  
  5101.       /* Do the same for categories.  Even though no references to these
  5102.       symbols are generated automatically by the compiler, it gives
  5103.       you a handle to pull them into an archive by hand. */
  5104.       sprintf (string, ".objc_category_name_%s_%s",
  5105.            IDENTIFIER_POINTER (CLASS_NAME (impent->imp_context)),
  5106.            IDENTIFIER_POINTER (CLASS_SUPER_NAME (impent->imp_context)));
  5107.       assemble_global (string);
  5108.       assemble_label (string);
  5109.     }
  5110. }
  5111.  
  5112. #ifdef DEBUG
  5113.  
  5114. static void
  5115. objc_debug (fp)
  5116.      FILE *fp;
  5117. {
  5118.   char *buf = (char *)xmalloc (256);
  5119.  
  5120.   {                /* dump function prototypes */
  5121.     tree loop = _OBJC_MODULES_decl;
  5122.  
  5123.     fprintf (fp, "\n\nfunction prototypes:\n");
  5124.     while (loop)
  5125.       {
  5126.     if (TREE_CODE (loop) == FUNCTION_DECL && DECL_INITIAL (loop))
  5127.       {
  5128.         /* we have a function definition - generate prototype */
  5129.             bzero (errbuf, BUFSIZE);
  5130.         gen_declaration (loop, errbuf);
  5131.         fprintf (fp, "%s;\n", errbuf);
  5132.       }
  5133.     loop = TREE_CHAIN (loop);
  5134.       }
  5135.   }
  5136.   {                /* dump global chains */
  5137.     tree loop;
  5138.     int i, index = 0, offset = 0;
  5139.     hash hashlist;
  5140.  
  5141.     for (i = 0; i < SIZEHASHTABLE; i++)
  5142.       {
  5143.     if (hashlist = nst_method_hash_list[i])
  5144.       {
  5145.         fprintf (fp, "\n\nnst_method_hash_list[%d]:\n", i);
  5146.         do
  5147.           {
  5148.         bzero (buf, 256);
  5149.         fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
  5150.         hashlist = hashlist->next;
  5151.           }
  5152.         while (hashlist);
  5153.       }
  5154.       }
  5155.     for (i = 0; i < SIZEHASHTABLE; i++)
  5156.       {
  5157.     if (hashlist = cls_method_hash_list[i])
  5158.       {
  5159.         fprintf (fp, "\n\ncls_method_hash_list[%d]:\n", i);
  5160.         do
  5161.           {
  5162.         bzero (buf, 256);
  5163.         fprintf (fp, "-%s;\n", gen_method_decl (hashlist->key, buf));
  5164.         hashlist = hashlist->next;
  5165.           }
  5166.         while (hashlist);
  5167.       }
  5168.       }
  5169.     fprintf (fp, "\nsel_refdef_chain:\n");
  5170.     for (loop = sel_refdef_chain; loop; loop = TREE_CHAIN (loop))
  5171.       {
  5172.     fprintf (fp, "(index: %4d offset: %4d) %s\n", index, offset,
  5173.          IDENTIFIER_POINTER (TREE_VALUE (loop)));
  5174.     index++;
  5175.     /* add one for the '\0' character */
  5176.     offset += IDENTIFIER_LENGTH (TREE_VALUE (loop)) + 1;
  5177.       }
  5178.     fprintf (fp, "\n (max_selector_index: %4d.\n", max_selector_index);
  5179.   }
  5180. }
  5181. #endif
  5182.  
  5183. void
  5184. print_lang_statistics ()
  5185. {
  5186. }
  5187.